import React, { useRef, useEffect, useState, Suspense } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import ConfirmDialog from '../../components/ConfirmDialog'
import { usePhotoNarrator } from '../../utils/photoNarrator'
import logoImg from '../../assets/3dimg/logo2.png'
import allImg from '../../assets/3dimg/allTime/all.png'
import alldzzImg from '../../assets/3dimg/allTime/alldzz.png'
import dacImg from '../../assets/3dimg/allTime/dac.png'
import dayaImg from '../../assets/3dimg/allTime/daya.png'
import ergeImg from '../../assets/3dimg/allTime/erge.png'
import fuImg from '../../assets/3dimg/allTime/fu.png'
import fuhaoImg from '../../assets/3dimg/allTime/fuhao.png'
import guo13Img from '../../assets/3dimg/allTime/guo13.png'
import shoudiImg from '../../assets/3dimg/allTime/shoudi.png'
import wugeImg from '../../assets/3dimg/allTime/wuge.png'
import wunaiqunImg from '../../assets/3dimg/allTime/wunaiqun.png'
import yangmingImg from '../../assets/3dimg/allTime/yangming.png'
import zhang77Img from '../../assets/3dimg/allTime/zhang77.png'
import zhao3Img from '../../assets/3dimg/allTime/zhao3.png'
import liu17Img from '../../assets/3dimg/allTime/liu17.png'
import img1allImg from '../../assets/3dimg/allTime/1all.png'
import img3allImg from '../../assets/3dimg/allTime/3all.png'
import img4allImg from '../../assets/3dimg/allTime/4all.png'
import img5allImg from '../../assets/3dimg/allTime/5all.png'
import img10allImg from '../../assets/3dimg/allTime/10all.png'
import img13allImg from '../../assets/3dimg/allTime/13all.png'
import img17allImg from '../../assets/3dimg/allTime/17all.png'
import img25allImg from '../../assets/3dimg/allTime/25all.png'
import img27allImg from '../../assets/3dimg/allTime/27all.png'
import img36allImg from '../../assets/3dimg/allTime/36all.png'
import img55allImg from '../../assets/3dimg/allTime/55all.png'
import img77allImg from '../../assets/3dimg/allTime/77all.png'
import liallImg from '../../assets/3dimg/allTime/liall.png'
import lixiaoxuallImg from '../../assets/3dimg/allTime/lixiaoxuall.png'
import champion2017Img from '../../assets/3dimg/qizhi/2017-2018.png'
import champion2021Img from '../../assets/3dimg/qizhi/2021-2022.png'
import champion2022Img from '../../assets/3dimg/qizhi/2022-2023.png'
import champion2023Img from '../../assets/3dimg/qizhi/2023-2024.png'
import jiaolianzhuImg from '../../assets/3dimg/allTime/jiaolianzhu.png'
import shareAfcbImg from '../../assets/3dimg/allTime/share_afcb133b8061cb6ef143eaebb2ec5c2c.png'
import { Canvas, useFrame, useThree, useLoader, extend } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
import * as THREE from 'three'

// 扩展Three.js组件
extend({ Object3D: THREE.Object3D, Group: THREE.Group })

// 扩展window类型声明
declare global {
  interface Window {
    imageInteractionState?: {
      nearestImage: {
        name: string
        position: THREE.Vector3
        distance: number
        imageUrl: string
      } | null
      isViewingImage: boolean
      viewingImageData: {
        name: string
        position: THREE.Vector3
        imageUrl: string
        originalCameraPosition: THREE.Vector3
        originalCameraRotation: THREE.Euler
      } | null
      cameraPosition: THREE.Vector3
      cameraRotation: THREE.Euler
    }
  }
}

// 视角类型定义
type CameraMode = 'firstPerson' | 'thirdPerson'

// 碰撞检测系统
interface CollisionBox {
  minX: number
  maxX: number
  minY: number
  maxY: number
  minZ: number
  maxZ: number
}

// 玩家角色组件
const PlayerCharacter: React.FC<{ 
  position: React.MutableRefObject<THREE.Vector3>
  rotation: React.MutableRefObject<THREE.Euler>
  visible: boolean
  isMoving: boolean
  moveDirection: 'forward' | 'backward' | 'left' | 'right' | 'idle'
  isJumping: boolean
  characterModel: string // 新增：角色模型路径
}> = ({ position, rotation, visible, isMoving, moveDirection, isJumping, characterModel }) => {
  const { scene } = useThree()
  const model = useLoader(GLTFLoader, characterModel)
  const addedRef = useRef(false)
  const mixerRef = useRef<THREE.AnimationMixer | null>(null)
  const walkActionRef = useRef<THREE.AnimationAction | null>(null)
  const walkBackwardActionRef = useRef<THREE.AnimationAction | null>(null)
  const walkLeftActionRef = useRef<THREE.AnimationAction | null>(null)
  const walkRightActionRef = useRef<THREE.AnimationAction | null>(null)
  const jumpActionRef = useRef<THREE.AnimationAction | null>(null)
  const idleActionRef = useRef<THREE.AnimationAction | null>(null)
  const currentActionRef = useRef<THREE.AnimationAction | null>(null)
  
  useEffect(() => {
    if (model?.scene && !addedRef.current) {
      // 调整模型大小以适应展览馆
      model.scene.scale.setScalar(1.2) // 放大人物
      model.scene.visible = visible
      scene.add(model.scene)
      addedRef.current = true
      
      // 初始化动画混合器
      mixerRef.current = new THREE.AnimationMixer(model.scene)
      
      // 加载走路动画（使用Walking.fbx）
      const loader = new FBXLoader()
      loader.load('/3dguan/Walking.fbx', (walkAnimation) => {
        if (walkAnimation.animations[0]) {
          walkActionRef.current = mixerRef.current!.clipAction(walkAnimation.animations[0])
                walkActionRef.current.setLoop(THREE.LoopRepeat, Infinity)
                walkActionRef.current.fadeIn(0.3)
        } else {
          console.error('走路动画加载失败：没有找到动画')
        }
      }, undefined, (error) => {
        console.error('走路动画加载错误:', error)
      })
      
      // 加载后退动画（使用Walking Backwards.fbx）
            loader.load('/3dguan/Walking Backwards.fbx', (walkBackwardAnimation) => {
              if (walkBackwardAnimation.animations[0]) {
                walkBackwardActionRef.current = mixerRef.current!.clipAction(walkBackwardAnimation.animations[0])
                walkBackwardActionRef.current.setLoop(THREE.LoopRepeat, Infinity)
                walkBackwardActionRef.current.fadeIn(0.3)
              } else {
                console.error('后退动画加载失败：没有找到动画')
              }
            }, undefined, (error) => {
              console.error('后退动画加载错误:', error)
            })

            loader.load('/3dguan/Walk Left.fbx', (walkLeftAnimation) => {
              if (walkLeftAnimation.animations[0]) {
                walkLeftActionRef.current = mixerRef.current!.clipAction(walkLeftAnimation.animations[0])
                walkLeftActionRef.current.setLoop(THREE.LoopRepeat, Infinity)
                walkLeftActionRef.current.fadeIn(0.3)
              } else {
                console.error('左移动画加载失败：没有找到动画')
              }
            }, undefined, (error) => {
              console.error('左移动画加载错误:', error)
            })

            loader.load('/3dguan/Walk Right.fbx', (walkRightAnimation) => {
              if (walkRightAnimation.animations[0]) {
                walkRightActionRef.current = mixerRef.current!.clipAction(walkRightAnimation.animations[0])
                walkRightActionRef.current.setLoop(THREE.LoopRepeat, Infinity)
                walkRightActionRef.current.fadeIn(0.3)
              } else {
                console.error('右移动画加载失败：没有找到动画')
              }
            }, undefined, (error) => {
              console.error('右移动画加载错误:', error)
            })
      
      // 加载跳跃动画（使用Jumping.fbx）
      loader.load('/3dguan/Jumping.fbx', (jumpAnimation) => {
        if (jumpAnimation.animations[0]) {
          jumpActionRef.current = mixerRef.current!.clipAction(jumpAnimation.animations[0])
          jumpActionRef.current.setLoop(THREE.LoopOnce, 1) // 跳跃动画只播放一次
          jumpActionRef.current.clampWhenFinished = true // 播放完后保持在最后一帧
        } else {
          console.error('跳跃动画加载失败：没有找到动画')
        }
      }, undefined, (error) => {
        console.error('跳跃动画加载错误:', error)
      })
      
      // 加载待机动画（使用现有的zhanli动画）
      loader.load('/animations/zhanli.fbx', (idleAnimation) => {
        if (idleAnimation.animations[0]) {
          idleActionRef.current = mixerRef.current!.clipAction(idleAnimation.animations[0])
          idleActionRef.current.setLoop(THREE.LoopRepeat, Infinity)
          idleActionRef.current.fadeIn(0.3)
          currentActionRef.current = idleActionRef.current
          currentActionRef.current.play()
        }
      })
    }
    
    return () => {
      if (model?.scene && addedRef.current) {
        scene.remove(model.scene)
        addedRef.current = false
        if (mixerRef.current) {
          mixerRef.current.stopAllAction()
          mixerRef.current = null
        }
      }
    }
  }, [model, scene, visible])
  
  // 缓存上次的动画状态
  const lastAnimationStateRef = useRef('')
  
  // 处理动画切换
  useEffect(() => {
    if (!mixerRef.current || !walkActionRef.current || !walkBackwardActionRef.current || !walkLeftActionRef.current || !walkRightActionRef.current || !jumpActionRef.current || !idleActionRef.current) {
      return
    }
    
    // 只在状态真正改变时才切换动画
    const currentState = `${isMoving}-${moveDirection}-${isJumping}`
    
    if (currentState === lastAnimationStateRef.current) {
      return // 状态没有变化，不需要切换动画
    }
    
    lastAnimationStateRef.current = currentState
    
    if (isJumping) {
      // 跳跃动画优先级最高
      if (currentActionRef.current !== jumpActionRef.current) {
        if (currentActionRef.current) {
          currentActionRef.current.fadeOut(0.2)
        }
        jumpActionRef.current.reset().fadeIn(0.2).play()
        currentActionRef.current = jumpActionRef.current
        
        // 监听跳跃动画结束事件
        const onJumpFinished = () => {
          jumpActionRef.current?.getMixer().removeEventListener('finished', onJumpFinished)
          // 跳跃结束后根据当前状态切换到相应动画
                 if (isMoving) {
                   if (moveDirection === 'forward') {
                     walkActionRef.current?.reset().fadeIn(0.3).play()
                     currentActionRef.current = walkActionRef.current
                   } else if (moveDirection === 'backward') {
                     walkBackwardActionRef.current?.reset().fadeIn(0.3).play()
                     currentActionRef.current = walkBackwardActionRef.current
                   } else if (moveDirection === 'left') {
                     walkLeftActionRef.current?.reset().fadeIn(0.3).play()
                     currentActionRef.current = walkLeftActionRef.current
                   } else if (moveDirection === 'right') {
                     walkRightActionRef.current?.reset().fadeIn(0.3).play()
                     currentActionRef.current = walkRightActionRef.current
                   }
                 } else {
                   idleActionRef.current?.reset().fadeIn(0.3).play()
                   currentActionRef.current = idleActionRef.current
                 }
        }
        jumpActionRef.current.getMixer().addEventListener('finished', onJumpFinished)
      }
    } else if (!isMoving) {
      // 切换到待机动画
      if (currentActionRef.current !== idleActionRef.current) {
        if (currentActionRef.current) {
          currentActionRef.current.fadeOut(0.3)
        }
        idleActionRef.current.reset().fadeIn(0.3).play()
        currentActionRef.current = idleActionRef.current
      }
    } else if (moveDirection === 'forward') {
      // 切换到前进动画
      if (currentActionRef.current !== walkActionRef.current) {
        if (currentActionRef.current) {
          currentActionRef.current.fadeOut(0.3)
        }
        walkActionRef.current.reset().fadeIn(0.3).play()
        currentActionRef.current = walkActionRef.current
      }
    } else if (moveDirection === 'backward') {
      // 切换到后退动画
      if (currentActionRef.current !== walkBackwardActionRef.current) {
        if (currentActionRef.current) {
          currentActionRef.current.fadeOut(0.3)
        }
        walkBackwardActionRef.current.reset().fadeIn(0.3).play()
        currentActionRef.current = walkBackwardActionRef.current
      }
    } else if (moveDirection === 'left') {
      // 切换到左移动画
      if (currentActionRef.current !== walkLeftActionRef.current) {
        if (currentActionRef.current) {
          currentActionRef.current.fadeOut(0.3)
        }
        walkLeftActionRef.current.reset().fadeIn(0.3).play()
        currentActionRef.current = walkLeftActionRef.current
      }
    } else if (moveDirection === 'right') {
      // 切换到右移动画
      if (currentActionRef.current !== walkRightActionRef.current) {
        if (currentActionRef.current) {
          currentActionRef.current.fadeOut(0.3)
        }
        walkRightActionRef.current.reset().fadeIn(0.3).play()
        currentActionRef.current = walkRightActionRef.current
      }
    }
  }, [isMoving, moveDirection, isJumping])
  
  // 实时更新位置、旋转和动画
  useFrame((_state, delta) => {
    if (model?.scene) {
      model.scene.position.copy(position.current)
      model.scene.rotation.copy(rotation.current)
      model.scene.visible = visible
      
      // 更新动画混合器
      if (mixerRef.current) {
        mixerRef.current.update(delta)
      }
    }
  })
  
  return null
}

// 移动控制组件
const MovementControls: React.FC<{ 
  cameraMode: CameraMode
  playerPosition: React.MutableRefObject<THREE.Vector3>
  playerRotation: React.MutableRefObject<THREE.Euler>
  setIsPlayerMoving: (moving: boolean) => void
  setPlayerMoveDirection: (direction: 'forward' | 'backward' | 'left' | 'right' | 'idle') => void
  setIsPlayerJumping: (jumping: boolean) => void
}> = ({ cameraMode, playerPosition, playerRotation, setIsPlayerMoving, setPlayerMoveDirection, setIsPlayerJumping }) => {
  const { camera } = useThree()
  const [isPointerLocked, setIsPointerLocked] = useState(false)
  const keys = useRef({
    w: false,
    a: false,
    s: false,
    d: false,
    ' ': false, // 空格键跳跃
  })
  
  // 跳跃状态
  const jumpState = useRef({
    isJumping: false,
    velocity: 0,
    groundHeight: 2,
    maxJumpHeight: 4, // 适中的跳跃高度
    gravity: -0.008, // 适中的重力，平衡梦幻和自然
    jumpForce: 0.18, // 适中的跳跃力
    airResistance: 0.999, // 保持空气阻力
    bounceDamping: 0.75,  // 适中的落地缓冲
    minVelocity: 0.005, // 适中的最小速度阈值
  })
  
  // 移动状态
  const moveState = useRef({
    targetX: 0,
    targetZ: 0,
    currentX: 0,
    currentZ: 0,
    moveSpeed: 0.08, // 进一步增加移动速度
    smoothFactor: 0.3, // 增加移动平滑因子，让移动更响应
  })

  // 碰撞检测函数
  const checkCollision = (newX: number, newZ: number, newY: number): boolean => {
    const playerRadius = 0.3 // 玩家碰撞半径
    const playerHeight = 1.8 // 玩家高度
    
    // 检查是否与任何碰撞体发生碰撞
    for (const collisionBox of collisionBoxes) {
      if (newX + playerRadius > collisionBox.minX && 
          newX - playerRadius < collisionBox.maxX &&
          newZ + playerRadius > collisionBox.minZ && 
          newZ - playerRadius < collisionBox.maxZ &&
          newY + playerHeight > collisionBox.minY && 
          newY < collisionBox.maxY) {
        return true // 发生碰撞
      }
    }
    return false // 无碰撞
  }

  // 计算基于楼梯/平台的目标地面高度
  const getTargetGroundHeight = (): number => {
    if (cameraMode === 'firstPerson') {
      return 3 // 第一人称保持人眼高度
    } else {
      return 0 // 第三人称数字人站在地面上
    }
  }


  // 定义所有碰撞体
  const collisionBoxes: CollisionBox[] = [
    // 外墙
    { minX: -30, maxX: -29.9, minY: 0, maxY: 8, minZ: -20, maxZ: 20 }, // 左墙
    { minX: 29.9, maxX: 30, minY: 0, maxY: 8, minZ: -20, maxZ: 20 }, // 右墙
    { minX: -30, maxX: 30, minY: 0, maxY: 8, minZ: -20, maxZ: -19.9 }, // 后墙
    { minX: -30, maxX: 30, minY: 0, maxY: 8, minZ: 19.9, maxZ: 20 }, // 前墙（已封闭）
    
    // 内部隔断墙
    { minX: 7.85, maxX: 8.15, minY: 0, maxY: 8, minZ: -15, maxZ: 15 }, // 主垂直墙
    { minX: -15.5, maxX: -0.5, minY: 0, maxY: 8, minZ: 7.85, maxZ: 8.15 }, // 左侧水平墙
    { minX: -15.5, maxX: -0.5, minY: 0, maxY: 8, minZ: -8.15, maxZ: -7.85 }, // 左侧下方墙
    { minX: 14.95, maxX: 30.15, minY: 0, maxY: 8, minZ: 7.85, maxZ: 8.15 }, // 右侧上方墙（左端与11号墙相交，右端贴外墙）
    // 右侧中间墙（已删除）
    { minX: 14.95, maxX: 30.15, minY: 0, maxY: 8, minZ: -8.15, maxZ: -7.85 }, // 右侧下方墙（左端与11号墙相交，右端贴外墙）
    { minX: 14.75, maxX: 15.25, minY: 0, maxY: 8, minZ: -16, maxZ: -8 }, // 小走廊墙（加厚0.5并略微外移）
    { minX: 14.85, maxX: 15.35, minY: 0, maxY: 8, minZ: 8.15, maxZ: 14.15 }, // 12号墙：与8号墙贴合（Z最小对齐8号墙外侧面）

    // 会议桌与椅子的碰撞（位于 8/10 号墙房间中心，桌 8×3）
    { minX: 22.55 - 4.2, maxX: 22.55 + 4.2, minY: 0, maxY: 1, minZ: -1.6, maxZ: 1.6 }, // 桌体
    // 椅子带宽碰撞条（长边两侧）
    { minX: 22.55 - 4.2, maxX: 22.55 + 4.2, minY: 0, maxY: 1, minZ: 2.3, maxZ: 2.6 },
    { minX: 22.55 - 4.2, maxX: 22.55 + 4.2, minY: 0, maxY: 1, minZ: -2.6, maxZ: -2.3 },
    // 短边两端椅子
    { minX: 22.55 - 4.6, maxX: 22.55 - 4.2, minY: 0, maxY: 1, minZ: -0.4, maxZ: 0.4 },
    { minX: 22.55 + 4.2, maxX: 22.55 + 4.6, minY: 0, maxY: 1, minZ: -0.4, maxZ: 0.4 },

    // 会议室中轴墙（阻挡）：两侧留门洞，中间为实体
    { minX: 14.95, maxX: 15.1,  minY: 0, maxY: 4.2, minZ: -8.0, maxZ: -7.4 }, // 左侧门洞上边缘墙
    { minX: 14.95, maxX: 15.1,  minY: 0, maxY: 4.2, minZ: -5.6, maxZ: 5.6 },  // 中央实体墙
    { minX: 14.95, maxX: 15.1,  minY: 0, maxY: 4.2, minZ: 7.4,  maxZ: 8.0 },  // 右侧门洞上边缘墙

    // 展示台碰撞体已删除
    
    // 中央雕塑碰撞体（已删除）
    // { minX: -1.5, maxX: 1.5, minY: 0, maxY: 3, minZ: -1.5, maxZ: 1.5 },

    // 大厅前台（防穿透）- 居中放置，朝向2号墙（-X）
    // 旋转90°后（整体向右平移5m）：占地沿 x 约 1.6、沿 z 约 6.2
    { minX: 4.2, maxX: 5.8, minY: 0, maxY: 1.3, minZ: -3.2, maxZ: 3.2 },
    // 前台两侧大型盆栽（碰撞）- X=8，Z≈±4.6（加高版）
    { minX: 7.3, maxX: 8.7, minY: 0, maxY: 3.8, minZ: -5.3, maxZ: -3.9 },
    { minX: 7.3, maxX: 8.7, minY: 0, maxY: 3.8, minZ: 3.9,  maxZ: 5.3 },
  ]

  useEffect(() => {
    // 初始化移动状态
    moveState.current.currentX = camera.position.x
    moveState.current.currentZ = camera.position.z
    moveState.current.targetX = camera.position.x
    moveState.current.targetZ = camera.position.z
    
    const handleKeyDown = (event: KeyboardEvent) => {
      const key = event.key.toLowerCase()
      if (key === ' ') {
        // 只在按下时触发跳跃，避免重复触发
        if (!keys.current[' ']) {
          keys.current[' '] = true
          // 开始跳跃
          if (!jumpState.current.isJumping) {
            if (cameraMode === 'firstPerson') {
              // 第一人称：使用物理跳跃
              jumpState.current.isJumping = true
              jumpState.current.velocity = jumpState.current.jumpForce
            } else if (cameraMode === 'thirdPerson') {
              // 第三人称：使用动画跳跃
              setIsPlayerJumping(true)
              // 1秒后重置跳跃状态（动画播放时间）
              setTimeout(() => {
                setIsPlayerJumping(false)
              }, 1000)
            }
          }
        }
      } else if (key in keys.current) {
        keys.current[key as keyof typeof keys.current] = true
      }
    }

    const handleKeyUp = (event: KeyboardEvent) => {
      const key = event.key.toLowerCase()
      if (key === ' ') {
        keys.current[' '] = false
      } else if (key in keys.current) {
        keys.current[key as keyof typeof keys.current] = false
      }
    }

    const handlePointerLockChange = () => {
      // 兼容任意锁定元素（我们现在在 canvas 上申请 pointer lock）
      setIsPointerLocked(document.pointerLockElement != null)
    }

    window.addEventListener('keydown', handleKeyDown)
    window.addEventListener('keyup', handleKeyUp)
    document.addEventListener('pointerlockchange', handlePointerLockChange)

    return () => {
      window.removeEventListener('keydown', handleKeyDown)
      window.removeEventListener('keyup', handleKeyUp)
      document.removeEventListener('pointerlockchange', handlePointerLockChange)
    }
  }, [camera, cameraMode, setIsPlayerJumping])

  useFrame(() => {
    // 只在鼠标锁定时才允许移动
    if (!isPointerLocked) return

    const moveSpeed = 0.05 // 减慢移动速度，让移动更优雅
    const direction = new THREE.Vector3()

    // 计算移动方向（只考虑水平移动）- 修复方向
    let isMoving = false
    let moveDirection: 'forward' | 'backward' | 'left' | 'right' | 'idle' = 'idle'
    
    // 根据视角模式调整移动方向
    if (cameraMode === 'firstPerson') {
      // 第一人称移动方向
      if (keys.current.w) { direction.z -= moveSpeed; isMoving = true; moveDirection = 'forward' }  // W前进
      if (keys.current.s) { direction.z += moveSpeed; isMoving = true; moveDirection = 'backward' }  // S后退
      if (keys.current.a) { direction.x -= moveSpeed; isMoving = true; moveDirection = 'left' }  // A左移
      if (keys.current.d) { direction.x += moveSpeed; isMoving = true; moveDirection = 'right' }  // D右移
    } else {
      // 第三人称移动方向
      if (keys.current.w) { direction.z += moveSpeed; isMoving = true; moveDirection = 'forward' }  // W前进
      if (keys.current.s) { direction.z -= moveSpeed; isMoving = true; moveDirection = 'backward' }  // S后退
      if (keys.current.a) { direction.x += moveSpeed; isMoving = true; moveDirection = 'left' }  // A左移
      if (keys.current.d) { direction.x -= moveSpeed; isMoving = true; moveDirection = 'right' }  // D右移
    }
    
    // 如果没有移动，设置为idle
    if (!isMoving) {
      moveDirection = 'idle'
    }
    
    // 更新移动状态（仅在第三人称模式下）
    if (cameraMode === 'thirdPerson') {
      // console.log('第三人称移动状态:', { isMoving, moveDirection })
      setIsPlayerMoving(isMoving)
      setPlayerMoveDirection(moveDirection)
    }

    // 根据视角模式应用不同的旋转
    let horizontalRotation: THREE.Euler
    if (cameraMode === 'firstPerson') {
      // 第一人称：使用相机旋转
      horizontalRotation = new THREE.Euler(0, camera.rotation.y, 0, 'YXZ')
    } else {
      // 第三人称：使用玩家角色旋转
      horizontalRotation = new THREE.Euler(0, playerRotation.current.y, 0, 'YXZ')
    }
    
    const horizontalQuaternion = new THREE.Quaternion().setFromEuler(horizontalRotation)
    direction.applyQuaternion(horizontalQuaternion)
    
    // 根据视角模式计算新位置
    let currentPosition: THREE.Vector3
    if (cameraMode === 'firstPerson') {
      currentPosition = camera.position
    } else {
      currentPosition = playerPosition.current
    }
    
    const proposedX = currentPosition.x + direction.x
    const proposedZ = currentPosition.z + direction.z

    // 基于楼梯/平台的目标地面高度（仅用于Y高度）
    const targetGround = getTargetGroundHeight()

    // 边界检测（展览馆边界：X: -30到30, Z: -20到20）
    const minX = -29
    const maxX = 29
    const minZ = -19
    const maxZ = 19
    
    // 检查边界和碰撞
    let newX = currentPosition.x
    let newZ = currentPosition.z

    // X方向
    if (proposedX >= minX && proposedX <= maxX && !checkCollision(proposedX, currentPosition.z, currentPosition.y)) {
      newX = proposedX
    }
    // Z方向
    if (proposedZ >= minZ && proposedZ <= maxZ && !checkCollision(currentPosition.x, proposedZ, currentPosition.y)) {
      newZ = proposedZ
    }

    // 更新位置
    if (cameraMode === 'firstPerson') {
      camera.position.x = newX
      camera.position.z = newZ
    } else {
      playerPosition.current.x = newX
      playerPosition.current.z = newZ
    }

    // 更稳定的跳跃逻辑（仅在第一人称模式下工作）
    if (jumpState.current.isJumping && cameraMode === 'firstPerson') {
      // 根据跳跃阶段调整速度
      const isRising = jumpState.current.velocity > 0
      const isFalling = jumpState.current.velocity < 0
      
      // 应用重力和空气阻力 - 使用适中的步长平衡梦幻和自然
      jumpState.current.velocity += jumpState.current.gravity * 0.6
      
      // 根据阶段应用不同的空气阻力
      if (isRising) {
        jumpState.current.velocity *= 0.996
      } else if (isFalling) {
        jumpState.current.velocity *= 0.999
      }
      
      // 第一人称模式下更新相机Y位置
      const currentY = camera.position.y
      const newY = currentY + jumpState.current.velocity
      
      // 检查是否落地 - 使用更精确的检测
      if (newY <= targetGround) {
        // 落地处理 - 直接停止，不弹跳
        camera.position.y = targetGround
        jumpState.current.isJumping = false
        jumpState.current.velocity = 0
      } else {
        camera.position.y = newY
      }
    } else if (cameraMode === 'firstPerson') {
      // 第一人称模式下平滑回到地面
      const currentY = camera.position.y
      const diff = targetGround - currentY
      if (Math.abs(diff) > 0.01) {
        camera.position.y += diff * 0.15
      } else {
        camera.position.y = targetGround
      }
    }

    // 确保相机保持水平，不会倾斜（只在鼠标锁定时）
    if (isPointerLocked) {
      camera.rotation.z = 0
    }

    // 防止Y位置因为浮点精度问题产生微小抖动
    if (Math.abs(camera.position.y - getTargetGroundHeight()) < 0.001) {
      camera.position.y = getTargetGroundHeight()
    }
  })

  // （移至ExhibitionHallScene）

  return null
}

// 鼠标视角控制组件
const MouseLookControls: React.FC<{
  cameraMode: CameraMode
  playerPosition: React.MutableRefObject<THREE.Vector3>
  playerRotation: React.MutableRefObject<THREE.Euler>
}> = ({ cameraMode, playerPosition, playerRotation }) => {
  const { camera } = useThree()
  const [isPointerLocked, setIsPointerLocked] = useState(false)
  const euler = useRef(new THREE.Euler(0, 0, 0, 'YXZ'))
  const sensitivity = 0.002
  
  // 相机距离管理
  const fixedCameraDistance = 1.5 // 增加摄像机距离以适应放大的人物
  const cameraHeight = 3.2 // 调整摄像机高度以适应放大的人物
  

  useEffect(() => {
    // 设置初始视角：面向展览馆大厅
    // 从左墙入口面向展览馆大厅
    const yRotation = 3 * Math.PI / 2  // 270度
    
    // 设置相机旋转
    camera.rotation.set(0, yRotation, 0, 'YXZ')
    euler.current.set(0, yRotation, 0, 'YXZ')
    
    const handlePointerLockChange = () => {
      const wasLocked = isPointerLocked
      const nowLocked = document.pointerLockElement === document.body
      
      if (wasLocked && !nowLocked) {
        // 从锁定变为解锁：保持当前视角
        // 确保euler.current和camera.rotation保持同步
        euler.current.set(camera.rotation.x, camera.rotation.y, 0, 'YXZ')
      } else if (!wasLocked && nowLocked) {
        // 从解锁变为锁定：确保相机使用当前的euler值
        camera.rotation.set(euler.current.x, euler.current.y, 0, 'YXZ')
      }
      
      setIsPointerLocked(nowLocked)
    }

    const handleMouseMove = (event: MouseEvent) => {
      // 直接从 DOM 查询是否处于锁定，避免闭包拿到旧的 isPointerLocked
      const lockedNow = document.pointerLockElement != null
      if (!lockedNow) return

      const movementX = event.movementX || 0
      const movementY = event.movementY || 0

      if (cameraMode === 'firstPerson') {
        // 第一人称：直接控制相机旋转
        // 水平旋转（左右看）
        euler.current.y -= movementX * sensitivity
        
        // 垂直旋转（上下看）- 修复方向
        euler.current.x -= movementY * sensitivity
        
        // 限制垂直视角范围（-30度到30度，更接近平视）
        const maxVerticalAngle = Math.PI / 6 // 30度
        euler.current.x = Math.max(-maxVerticalAngle, Math.min(maxVerticalAngle, euler.current.x))

        // 强制Z轴旋转始终为0，确保水平视角
        euler.current.z = 0

        // 使用正确的旋转顺序来避免倾斜
        // 先设置Y轴旋转（水平），再设置X轴旋转（垂直）
        camera.rotation.set(euler.current.x, euler.current.y, 0, 'YXZ')
      } else {
        // 第三人称：控制玩家角色旋转和相机围绕角色的角度
        // 水平旋转（左右看）
        playerRotation.current.y -= movementX * sensitivity
        
        // 垂直旋转（上下看）- 控制相机高度
        euler.current.x += movementY * sensitivity
        
        // 限制垂直视角范围（-30度到30度，更接近平视）
        const maxVerticalAngle = Math.PI / 6 // 30度
        euler.current.x = Math.max(-maxVerticalAngle, Math.min(maxVerticalAngle, euler.current.x))

        // 强制Z轴旋转始终为0，确保水平视角
        euler.current.z = 0
        
        // 简化版本：不需要距离调整
      }
    }

    const handleClick = () => {
      const el = document.querySelector('canvas') as HTMLElement | null
      if (el && document.pointerLockElement !== el) {
        el.requestPointerLock()
      }
    }

    document.addEventListener('pointerlockchange', handlePointerLockChange)
    document.addEventListener('mousemove', handleMouseMove)
    document.addEventListener('click', handleClick)

    return () => {
      document.removeEventListener('pointerlockchange', handlePointerLockChange)
      document.removeEventListener('mousemove', handleMouseMove)
      document.removeEventListener('click', handleClick)
    }
  }, [camera, cameraMode, isPointerLocked, playerRotation, playerPosition])

  // 持续确保相机保持水平并处理第三人称相机跟随
  useFrame(() => {
    // 只在鼠标锁定时强制Z轴旋转为0，确保水平视角
    if (isPointerLocked) {
      camera.rotation.z = 0
    }
    
    // 第三人称相机跟随逻辑
    if (cameraMode === 'thirdPerson') {
      const playerPos = playerPosition.current
      const playerRot = playerRotation.current
      
      // 根据垂直旋转调整相机高度
      const verticalAngle = euler.current.x
      const adjustedCameraHeight = cameraHeight + Math.sin(verticalAngle) * 2.0 // 根据垂直角度调整高度
      
      // 计算相机目标位置（在玩家后方）
      const cameraOffset = new THREE.Vector3(
        -Math.sin(playerRot.y) * fixedCameraDistance,
        adjustedCameraHeight,
        -Math.cos(playerRot.y) * fixedCameraDistance
      )
      
      const targetCameraPos = new THREE.Vector3(
        playerPos.x + cameraOffset.x,
        playerPos.y + cameraOffset.y,
        playerPos.z + cameraOffset.z
      )
      
      // 平滑移动相机到目标位置
      camera.position.lerp(targetCameraPos, 0.15)
      
      // 根据垂直角度调整相机看向的目标高度
      const lookAtHeight = 2.4 + Math.sin(verticalAngle) * 0 // 根据垂直角度调整看向高度，适应放大的人物
      const lookAtTarget = new THREE.Vector3(
        playerPos.x,
        playerPos.y + lookAtHeight,
        playerPos.z
      )
      
      camera.lookAt(lookAtTarget)
    }
  })

  return null
}

// 墙面数字标记函数已删除

// 图片交互逻辑组件（在Canvas内部，只处理逻辑）
const ImageInteractionLogic: React.FC = () => {
  const { camera, scene } = useThree()
  const [nearestImage, setNearestImage] = useState<{
    name: string
    position: THREE.Vector3
    distance: number
    imageUrl: string
  } | null>(null)
  const [isViewingImage, setIsViewingImage] = useState(false)
  const [viewingImageData, setViewingImageData] = useState<{
    name: string
    position: THREE.Vector3
    imageUrl: string
    originalCameraPosition: THREE.Vector3
    originalCameraRotation: THREE.Euler
  } | null>(null)
  
  // 图片位置数据
  const imagePositions = useRef<Array<{
    name: string
    position: THREE.Vector3
    type: 'player' | 'champion' | 'all'
    imageUrl: string
  }>>([])
  
  // 距离阈值
  const INTERACTION_DISTANCE = 3.0
  
  // 初始化图片位置数据
  useEffect(() => {
    // 13张球员图片位置（5号墙背后）
    const wallX = 8.2
    const startY = 3.0
    const startZ = -13
    const spacingX = 2.2
    
    const playerImages = [
      { name: '吴昌泽', url: dacImg },
      { name: '俞泽辰', url: dayaImg },
      { name: '李晓旭', url: ergeImg },
      { name: '凯尔-弗格', url: fuImg },
      { name: '付豪', url: fuhaoImg },
      { name: '乌戈-洛佩斯', url: wugeImg },
      { name: '杨鸣', url: yangmingImg },
      { name: '吴乃群', url: wunaiqunImg },
      { name: '郭艾伦', url: guo13Img },
      { name: '鄢手骐', url: shoudiImg },
      { name: '张镇麟', url: zhang77Img },
      { name: '赵继伟', url: zhao3Img },
      { name: '刘雁宇', url: liu17Img }
    ]
    
    playerImages.forEach((player, index) => {
      const z = startZ + index * spacingX
      imagePositions.current.push({
        name: player.name,
        position: new THREE.Vector3(wallX, startY, z),
        type: 'player',
        imageUrl: player.url
      })
    })
    
    // 4张冠军海报位置（5号墙上面）
    const championWallX = 7.8
    const championStartY = 6.4
    const championStartZ = -4.5
    const championSpacingX = 3.0
    
    const championImages = [
      { name: '2017-2018', url: champion2017Img },
      { name: '2021-2022', url: champion2021Img },
      { name: '2022-2023', url: champion2022Img },
      { name: '2023-2024', url: champion2023Img }
    ]
    
    championImages.forEach((champion, index) => {
      const z = championStartZ + index * championSpacingX
      imagePositions.current.push({
        name: champion.name,
        position: new THREE.Vector3(championWallX, championStartY, z),
        type: 'champion',
        imageUrl: champion.url
      })
    })
    
    // all.png图片位置（10号墙）
    imagePositions.current.push({
      name: '球员合影',
      position: new THREE.Vector3(14.99, 3, 0),
      type: 'all',
      imageUrl: allImg
    })
    
    // alldzz.png图片位置（3号墙）
    imagePositions.current.push({
      name: '全队新赛季定妆照',
      position: new THREE.Vector3(-29.99, 3, 0),
      type: 'all',
      imageUrl: alldzzImg
    })
    
    // 1号墙上的7张图片位置
    const wall1ImageList = [
      { img: img1allImg, name: '付豪' },
      { img: img3allImg, name: '赵继伟' },
      { img: img4allImg, name: '凯尔-弗格' },
      { img: img5allImg, name: '周俊成' },
      { img: img10allImg, name: '丛明晨' },
      { img: img13allImg, name: '郭艾伦' },
      { img: img17allImg, name: '刘雁宇' }
    ]
    
    // 计算1号墙图片位置（与ExhibitionHall中的布局保持一致）
    const imageSize = 5
    const spacing = 0.5
    const cols = 7
    const wall1StartX = -30
    const wall1StartY = 5.5
    
    wall1ImageList.forEach((imageData, index) => {
      const col = index % cols
      const row = Math.floor(index / cols)
      const x = wall1StartX + col * (imageSize + spacing) + imageSize / 2
      const y = wall1StartY - row * (imageSize + spacing) - imageSize / 2
      
      imagePositions.current.push({
        name: imageData.name,
        position: new THREE.Vector3(x, y, 19.80),
        type: 'all',
        imageUrl: imageData.img
      })
    })
    
    // 2号墙上的7张图片位置
    const wall2ImageList = [
      { img: img25allImg, name: '埃里克-莫兰德' },
      { img: img27allImg, name: '俞泽晨' },
      { img: img36allImg, name: '鄢手骐' },
      { img: img55allImg, name: '韩德君' },
      { img: img77allImg, name: '张镇麟' },
      { img: liallImg, name: '李虎翼' },
      { img: lixiaoxuallImg, name: '李晓旭' }
    ]
    
    // 计算2号墙图片位置（与1号墙布局保持一致）
    const wall2StartX = -30
    const wall2StartY = 5.5
    
    wall2ImageList.forEach((imageData, index) => {
      const col = index % cols
      const row = Math.floor(index / cols)
      const x = wall2StartX + col * (imageSize + spacing) + imageSize / 2
      const y = wall2StartY - row * (imageSize + spacing) - imageSize / 2
      
      imagePositions.current.push({
        name: imageData.name,
        position: new THREE.Vector3(x, y, -19.80),
        type: 'all',
        imageUrl: imageData.img
      })
    })
    
    // 6号墙图片位置
    imagePositions.current.push({
      name: '教练组',
      position: new THREE.Vector3(-7.85, 3, 8.16),
      type: 'all',
      imageUrl: jiaolianzhuImg
    })
    
    // 7号墙图片位置
    imagePositions.current.push({
      name: '球员合影',
      position: new THREE.Vector3(-7.85, 3, -8.16),
      type: 'all',
      imageUrl: shareAfcbImg
    })
  }, [])
  
  // 距离检测
  useFrame(() => {
    if (isViewingImage) return // 查看模式下不进行距离检测
    
    let nearest: { name: string; position: THREE.Vector3; distance: number; imageUrl: string } | null = null
    let minDistance = Infinity
    
    // 检查1号墙图片的实际位置
    scene.traverse((child: THREE.Object3D) => {
      if (child.userData.interactionPosition && child.userData.imageName) {
        const actualPosition = child.userData.interactionPosition
        const distance = camera.position.distanceTo(actualPosition)
        
        if (distance < minDistance && distance < INTERACTION_DISTANCE) {
          // 检查是否面向图片
          const cameraDirection = new THREE.Vector3()
          camera.getWorldDirection(cameraDirection)
          
          const toImage = new THREE.Vector3()
          toImage.subVectors(actualPosition, camera.position).normalize()
          
          // 计算面向角度（点积），值越接近1表示越面向图片
          const dotProduct = cameraDirection.dot(toImage)
          const facingThreshold = 0.3 // 面向阈值，可以调整（0-1之间，越接近1要求越精确面向）
          
          if (dotProduct > facingThreshold) {
            minDistance = distance
            nearest = {
              name: child.userData.imageName,
              position: actualPosition,
              distance,
              imageUrl: child.userData.imageUrl
            }
          }
        }
      }
    })
    
    // 检查其他图片（非1号墙和2号墙）
    imagePositions.current.forEach(image => {
      // 跳过1号墙和2号墙图片，因为已经通过场景遍历检查了
      if (image.name.includes('all.png') || image.position.z === -19.80) return
      
      const distance = camera.position.distanceTo(image.position)
      if (distance < minDistance && distance < INTERACTION_DISTANCE) {
        // 检查是否面向图片
        const cameraDirection = new THREE.Vector3()
        camera.getWorldDirection(cameraDirection)
        
        const toImage = new THREE.Vector3()
        toImage.subVectors(image.position, camera.position).normalize()
        
        // 计算面向角度（点积），值越接近1表示越面向图片
        const dotProduct = cameraDirection.dot(toImage)
        const facingThreshold = 0.3 // 面向阈值，可以调整（0-1之间，越接近1要求越精确面向）
        
        if (dotProduct > facingThreshold) {
          minDistance = distance
          nearest = {
            name: image.name,
            position: image.position,
            distance,
            imageUrl: image.imageUrl
          }
        }
      }
    })
    
    setNearestImage(nearest)
  })
  
  // F键交互（长按查看，松手退出）
  const isKeyHeldRef = useRef(false)
  
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key.toLowerCase() === 'f' && nearestImage && !isViewingImage && !isKeyHeldRef.current) {
        isKeyHeldRef.current = true
        
        // 进入查看模式
        setIsViewingImage(true)
        setViewingImageData({
          name: nearestImage.name,
          position: nearestImage.position,
          imageUrl: nearestImage.imageUrl,
          originalCameraPosition: camera.position.clone(),
          originalCameraRotation: camera.rotation.clone()
        })
      }
    }
    
    const handleKeyUp = (event: KeyboardEvent) => {
      if (event.key.toLowerCase() === 'f' && isViewingImage && isKeyHeldRef.current) {
        isKeyHeldRef.current = false
        
        // 退出查看模式
        if (viewingImageData) {
          setIsViewingImage(false)
          setViewingImageData(null)
        }
      }
    }
    
    document.addEventListener('keydown', handleKeyDown)
    document.addEventListener('keyup', handleKeyUp)
    
    return () => {
      document.removeEventListener('keydown', handleKeyDown)
      document.removeEventListener('keyup', handleKeyUp)
    }
  }, [nearestImage, isViewingImage, viewingImageData, camera])
  
  // 将状态传递给全局状态管理
  useEffect(() => {
    // 这里可以通过context或其他方式将状态传递给外部组件
    window.imageInteractionState = {
      nearestImage,
      isViewingImage,
      viewingImageData,
      cameraPosition: camera.position.clone(),
      cameraRotation: camera.rotation.clone()
    }
  }, [nearestImage, isViewingImage, viewingImageData, camera.position, camera.rotation])
  
  return null // 不返回任何UI元素
}

// 展览馆场景组件
const ExhibitionHallScene: React.FC = () => {
  const { scene, camera } = useThree()
  const meetingVideoRef = useRef<HTMLVideoElement | null>(null)
  const meetingVolumeRef = useRef(0)

  useEffect(() => {

    const cleanups: Array<() => void> = []

    // 创建地面
    const groundGeometry = new THREE.BoxGeometry(60, 0.2, 40)
    const groundMaterial = new THREE.MeshStandardMaterial({ color: '#f5f5dc' })
    const ground = new THREE.Mesh(groundGeometry, groundMaterial)
    ground.position.set(0, -0.1, 0)
    scene.add(ground)

    // 创建墙壁材质（统一使用外墙颜色）
    const wallMaterial = new THREE.MeshStandardMaterial({ color: '#f0f0f0' }) // 外墙颜色
    const redWallMaterial = wallMaterial
    const blueWallMaterial = wallMaterial
    const greenWallMaterial = wallMaterial
    
    
    // 外墙
    // 后墙
    const backWallGeometry = new THREE.BoxGeometry(60, 8, 0.2)
    const backWall = new THREE.Mesh(backWallGeometry, wallMaterial)
    backWall.position.set(0, 4, -20)
    scene.add(backWall)
    
    // 左墙
    const leftWallGeometry = new THREE.BoxGeometry(0.2, 8, 40)
    const leftWall = new THREE.Mesh(leftWallGeometry, wallMaterial)
    leftWall.position.set(-30, 4, 0)
    scene.add(leftWall)
    
    // 右墙
    const rightWallGeometry = new THREE.BoxGeometry(0.2, 8, 40)
    const rightWall = new THREE.Mesh(rightWallGeometry, wallMaterial)
    rightWall.position.set(30, 4, 0)
    scene.add(rightWall)

    // 前墙（已封闭）
    const frontWallGeometry = new THREE.BoxGeometry(60, 8, 0.2)
    const frontWall = new THREE.Mesh(frontWallGeometry, wallMaterial)
    frontWall.position.set(0, 4, 20)
    scene.add(frontWall)

    // 楼梯已删除

    // 二层小平台已删除（保留楼梯可视台阶），不再添加平台与护栏

    // 天花 - 方案A：线性灯带 + 平顶（每个房间一个顶）
    {
      const ceilingY = 8
      const ceilMat = new THREE.MeshStandardMaterial({ color: '#f2f2f2', roughness: 0.95 })
      const lampMat = new THREE.MeshStandardMaterial({ color: '#ffffff', emissive: '#ffffff', emissiveIntensity: 2.4 })
      const barT = 0.05
      const inset = 0.2
      const y = ceilingY - 0.02
      const addPerimeter = (cx: number, w: number, d: number) => {
        const longBarGeom = new THREE.BoxGeometry(w - inset * 2, barT, 0.06)
        const shortBarGeom = new THREE.BoxGeometry(0.06, barT, d - inset * 2)
        const top = new THREE.Mesh(longBarGeom, lampMat); top.position.set(cx, y, d/2 - inset); scene.add(top)
        const bottom = new THREE.Mesh(longBarGeom, lampMat); bottom.position.set(cx, y, -d/2 + inset); scene.add(bottom)
        const left = new THREE.Mesh(shortBarGeom, lampMat); left.position.set(cx - w/2 + inset, y, 0); scene.add(left)
        const right = new THREE.Mesh(shortBarGeom, lampMat); right.position.set(cx + w/2 - inset, y, 0); scene.add(right)
      }
      const addRectLight = (cx: number, cz: number, w: number, h: number, intensity: number) => {
        const rect = new THREE.RectAreaLight('#ffffff', intensity, w, h)
        rect.position.set(cx, ceilingY - 0.05, cz)
        rect.lookAt(cx, ceilingY - 1, cz)
        scene.add(rect)
      }

      // 左房间：x∈[-30,-1], z∈[-8,8]
      {
        const w = 29, d = 16, cx = -15.5, cz = 0
        const leftCeil = new THREE.Mesh(new THREE.BoxGeometry(w, 0.06, d), ceilMat)
        leftCeil.position.set(cx, ceilingY, cz)
        scene.add(leftCeil)
        addPerimeter(cx, w, d)
        addRectLight(cx, cz, 14, 3, 6)
      }
      // 右房间：x∈[8,30], z∈[-8,8]
      {
        const w = 22, d = 16, cx = 19, cz = 0
        const rightCeil = new THREE.Mesh(new THREE.BoxGeometry(w, 0.06, d), ceilMat)
        rightCeil.position.set(cx, ceilingY, cz)
        scene.add(rightCeil)
        addPerimeter(cx, w, d)
        addRectLight(cx, cz, 14, 3, 6)
      }
      // 大厅：分三块（避免覆盖左右房间）
      // 上块 z∈[8,20]
      {
        const w = 60, d = 12, cx = 0, cz = 14
        const ceil = new THREE.Mesh(new THREE.BoxGeometry(w, 0.06, d), ceilMat)
        ceil.position.set(cx, ceilingY, cz)
        scene.add(ceil)
        // 灯带沿此块周界
        const longBarGeom = new THREE.BoxGeometry(w - inset * 2, barT, 0.06)
        const shortBarGeom = new THREE.BoxGeometry(0.06, barT, d - inset * 2)
        const top = new THREE.Mesh(longBarGeom, lampMat); top.position.set(cx, y, cz + d/2 - inset); scene.add(top)
        const bottom = new THREE.Mesh(longBarGeom, lampMat); bottom.position.set(cx, y, cz - d/2 + inset); scene.add(bottom)
        const left = new THREE.Mesh(shortBarGeom, lampMat); left.position.set(-30 + inset, y, cz); scene.add(left)
        const right = new THREE.Mesh(shortBarGeom, lampMat); right.position.set(30 - inset, y, cz); scene.add(right)
        addRectLight(cx, cz, 20, 4, 8)
      }
      // 下块 z∈[-20,-8]
      {
        const w = 60, d = 12, cx = 0, cz = -14
        const ceil = new THREE.Mesh(new THREE.BoxGeometry(w, 0.06, d), ceilMat)
        ceil.position.set(cx, ceilingY, cz)
        scene.add(ceil)
        const longBarGeom = new THREE.BoxGeometry(w - inset * 2, barT, 0.06)
        const shortBarGeom = new THREE.BoxGeometry(0.06, barT, d - inset * 2)
        const top = new THREE.Mesh(longBarGeom, lampMat); top.position.set(cx, y, cz + d/2 - inset); scene.add(top)
        const bottom = new THREE.Mesh(longBarGeom, lampMat); bottom.position.set(cx, y, cz - d/2 + inset); scene.add(bottom)
        const left = new THREE.Mesh(shortBarGeom, lampMat); left.position.set(-30 + inset, y, cz); scene.add(left)
        const right = new THREE.Mesh(shortBarGeom, lampMat); right.position.set(30 - inset, y, cz); scene.add(right)
        addRectLight(cx, cz, 20, 4, 8)
      }
      // 中央走廊块：x∈[-1,8], z∈[-8,8]
      {
        const w = 9, d = 16, cx = 3.5, cz = 0
        const ceil = new THREE.Mesh(new THREE.BoxGeometry(w, 0.06, d), ceilMat)
        ceil.position.set(cx, ceilingY, cz)
        scene.add(ceil)
        addPerimeter(cx, w, d)
        addRectLight(cx, cz, 8, 3, 6)
      }
    }

    // 内部隔断墙 - 主垂直墙（红色）
    const mainVerticalWallGeometry = new THREE.BoxGeometry(0.3, 8, 30)
    const mainVerticalWall = new THREE.Mesh(mainVerticalWallGeometry, redWallMaterial)
    mainVerticalWall.position.set(8, 4, 0)
    scene.add(mainVerticalWall)

    // 左侧水平墙（蓝色）
    const leftHorizontalWallGeometry = new THREE.BoxGeometry(15, 8, 0.3)
    const leftHorizontalWall = new THREE.Mesh(leftHorizontalWallGeometry, blueWallMaterial)
    leftHorizontalWall.position.set(-8, 4, 8)
    scene.add(leftHorizontalWall)

    // 左侧下方墙（青色）
    const leftBottomWallGeometry = new THREE.BoxGeometry(15, 8, 0.3)
    const leftBottomWall = new THREE.Mesh(leftBottomWallGeometry, greenWallMaterial)
    leftBottomWall.position.set(-8, 4, -8)
    scene.add(leftBottomWall)

    // 右侧上方墙（青色）：右端贴外墙x=30，左端与11号墙x≈15.1相交 → 长度≈14.9
    const rightTopWallGeometry = new THREE.BoxGeometry(14.9, 8, 0.3)
    const rightTopWall = new THREE.Mesh(rightTopWallGeometry, greenWallMaterial)
    // 中心x = (30 + 15.1)/2 ≈ 22.55
    rightTopWall.position.set(22.55, 4, 8)
    scene.add(rightTopWall)

    // 右侧中间墙（已删除）

    // 右侧下方墙（蓝色）：右端贴外墙x=30，左端与11号墙x≈15.1相交 → 长度≈14.9
    const rightBottomWallGeometry = new THREE.BoxGeometry(14.9, 8, 0.3)
    const rightBottomWall = new THREE.Mesh(rightBottomWallGeometry, blueWallMaterial)
    // 中心x = (30 + 15.1)/2 ≈ 22.55
    rightBottomWall.position.set(22.55, 4, -8)
    scene.add(rightBottomWall)
 
    // 墙面数字标记已删除

    // 在1号墙上添加7张图片（均匀平铺）
    {
      const imageList = [
        { img: img1allImg, name: '付豪' },
        { img: img3allImg, name: '赵继伟' },
        { img: img4allImg, name: '凯尔-弗格' },
        { img: img5allImg, name: '周俊成' },
        { img: img10allImg, name: '丛明晨' },
        { img: img13allImg, name: '郭艾伦' },
        { img: img17allImg, name: '刘雁宇' }
      ]

      // 1号墙位置：z=19.5，面向内部（-Z方向）
      // 计算布局：7张图片，1行7列布局
      const imageSize = 5 // 每张图片的基础尺寸（稍微小一点）
      const spacing = 0.5 // 图片间距（稍微小一点）
      
      const cols = 7 // 1行7张
      
      // 计算起始位置（居中）
      const startX = -30      
      const startY = 5.5 // 固定在y=4的位置（墙面中心）

      imageList.forEach((imageData, index) => {
        const texture = new THREE.TextureLoader().load(imageData.img)
        texture.colorSpace = THREE.SRGBColorSpace
        texture.anisotropy = 4
        
        const imageMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
        const imageGeom = new THREE.PlaneGeometry(imageSize, imageSize)
        const imageMesh = new THREE.Mesh(imageGeom, imageMat)
        
        // 计算位置
        const col = index % cols
        const row = Math.floor(index / cols)
        const x = startX + col * (imageSize + spacing) + imageSize / 2
        const y = startY - row * (imageSize + spacing) - imageSize / 2
        
        // 1号墙位置：前墙内部表面z=19.9，图片贴在墙面上，稍微前移避免共面
        imageMesh.position.set(x, y, 19.80)
        imageMesh.rotation.y = 0 // 尝试不同的朝向
        imageMesh.scale.x = -1 // 翻转镜像，修正1号墙图片镜像问题
        
        // 图片加载完成后调整尺寸保持原始比例
        const updateImageSize = () => {
          if (texture.image) {
            const imageAspectRatio = texture.image.width / texture.image.height
            const imageWidth = imageSize * imageAspectRatio
            const imageHeight = imageSize
            
            // 更新几何体尺寸
            imageGeom.dispose()
            const newGeom = new THREE.PlaneGeometry(imageWidth, imageHeight)
            imageMesh.geometry = newGeom
            
            // 更新交互检测位置（使用实际渲染位置）
            const actualPosition = new THREE.Vector3(x, y, 19.80)
            imageMesh.userData.interactionPosition = actualPosition
            
            console.log(`1号墙图片 ${imageData.name} 尺寸调整完成: ${imageWidth.toFixed(2)} x ${imageHeight.toFixed(2)}`)
          } else {
            // 如果图片还没加载完成，继续等待
            setTimeout(updateImageSize, 100)
          }
        }
        
        // 设置图片的用户数据，用于交互检测
        imageMesh.userData.imageName = imageData.name
        imageMesh.userData.imageUrl = imageData.img
        imageMesh.userData.interactionPosition = new THREE.Vector3(x, y, 19.80)
        
        updateImageSize()
        scene.add(imageMesh)
        
        // 添加调试信息
        console.log(`1号墙图片 ${imageData.name} 已添加到场景，位置: (${x.toFixed(2)}, ${y.toFixed(2)}, 19.80)`)
      })

      console.log('在1号墙上添加7张图片（均匀平铺）')
    }
    

    // 在2号墙上添加7张图片（均匀平铺）
    {
      const imageList = [
        { img: img25allImg, name: '埃里克-默兰德' },
        { img: img27allImg, name: '俞泽晨' },
        { img: img36allImg, name: '鄢手骐' },
        { img: img55allImg, name: '韩德君' },
        { img: img77allImg, name: '张镇麟' },
        { img: liallImg, name: '李虎翼' },
        { img: lixiaoxuallImg, name: '李晓旭' }
      ]

      // 2号墙位置：z=-19.5，面向内部（+Z方向）
      // 计算布局：7张图片，1行7列布局
      const imageSize = 5 // 每张图片的基础尺寸（与1号墙保持一致）
      const spacing = 0.5 // 图片间距（与1号墙保持一致）
      const cols = 7
      
      // 计算起始位置（居中）
      const startX = -30      
      const startY = 5.5 // 固定在y=5.5的位置（与1号墙保持一致）

      imageList.forEach((imageData, index) => {
        const texture = new THREE.TextureLoader().load(imageData.img)
        texture.colorSpace = THREE.SRGBColorSpace
        texture.anisotropy = 4
        
        const material = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
        
        // 计算位置（1行7列布局）
        const col = index % cols
        const row = Math.floor(index / cols)
        const x = startX + col * (imageSize + spacing) + imageSize / 2
        const y = startY - row * (imageSize + spacing) - imageSize / 2
        
        // 2号墙位置：后墙内部表面z=-19.9，图片贴在墙面上，稍微前移避免共面
        const imageMesh = new THREE.Mesh(new THREE.PlaneGeometry(imageSize, imageSize), material)
        imageMesh.position.set(x, y, -19.80)
        imageMesh.rotation.y = 0 // 面向+z方向（朝向展馆内部）
        
        // 设置用户数据用于交互检测
        imageMesh.userData.imageName = imageData.name
        imageMesh.userData.imageUrl = imageData.img
        
        // 动态调整图片尺寸以保持比例（与1号墙保持一致）
        const updateImageSize = () => {
          if (texture.image && texture.image.width && texture.image.height) {
            const imageAspectRatio = texture.image.width / texture.image.height
            const imageWidth = imageSize * imageAspectRatio
            const imageHeight = imageSize
            
            // 更新几何体尺寸
            imageMesh.geometry.dispose()
            imageMesh.geometry = new THREE.PlaneGeometry(imageWidth, imageHeight)
            
            // 更新交互检测位置（使用实际渲染位置）
            const actualPosition = new THREE.Vector3(x, y, -19.80)
            imageMesh.userData.interactionPosition = actualPosition
            
            console.log(`2号墙图片 ${imageData.name} 尺寸调整完成: ${imageWidth.toFixed(2)} x ${imageHeight.toFixed(2)}`)
          } else {
            // 如果图片还没加载完成，继续等待
            setTimeout(updateImageSize, 100)
          }
        }
        
        updateImageSize()
        scene.add(imageMesh)
        
        // 添加调试信息
        console.log(`2号墙图片 ${imageData.name} 已添加到场景，位置: (${x.toFixed(2)}, ${y.toFixed(2)}, -19.80)`)
      })

      console.log('在2号墙上添加7张图片（均匀平铺）')
    }
    

    // 在10号墙上添加all.png图片
    {
      // 加载all.png图片纹理
      const texture = new THREE.TextureLoader().load(allImg)
      texture.colorSpace = THREE.SRGBColorSpace
      texture.anisotropy = 4
      
      // 设置一个默认尺寸，等图片加载完成后再调整
      const baseHeight = 5 // 增加高度，让图片更大
      const defaultWidth = 6 // 增加默认宽度
      
      const imageMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
      const imageGeom = new THREE.PlaneGeometry(defaultWidth, baseHeight)
      const imageMesh = new THREE.Mesh(imageGeom, imageMat)
      
      // 10号墙位置：x=14.5, z=-4，面向内部（-X方向）
      // 图片贴在墙面上，稍微前移避免共面
      imageMesh.position.set(14.99, 3, 0)
      imageMesh.rotation.y = -Math.PI / 2 // 面向内部
      
      // 图片加载完成后调整尺寸保持原始比例
      const updateImageSize = () => {
        if (texture.image) {
          const imageAspectRatio = texture.image.width / texture.image.height
          const imageWidth = baseHeight * imageAspectRatio
          
          // 更新几何体尺寸
          imageGeom.dispose()
          const newImageGeom = new THREE.PlaneGeometry(imageWidth, baseHeight)
          imageMesh.geometry = newImageGeom
          
          console.log('在10号墙上添加all.png图片，保持原始比例:', imageWidth, 'x', baseHeight)
        }
      }
      
      // 检查图片是否已经加载完成
      if (texture.image) {
        updateImageSize()
      } else {
        // 如果还没加载完成，等待加载完成
        const checkLoaded = () => {
          if (texture.image) {
            updateImageSize()
          } else {
            // 继续等待
            setTimeout(checkLoaded, 100)
          }
        }
        checkLoaded()
      }
      
      scene.add(imageMesh)
      console.log('在10号墙上添加all.png图片（默认尺寸）')
    }

    // 在3号墙上添加alldzz.png图片
    {
      // 加载alldzz.png图片纹理
      const texture = new THREE.TextureLoader().load(alldzzImg)
      texture.colorSpace = THREE.SRGBColorSpace
      texture.anisotropy = 4
      
      // 设置一个默认尺寸，等图片加载完成后再调整
      const baseHeight = 11 // 进一步增加高度，让图片更大
      const defaultWidth = 12 // 进一步增加默认宽度
      
      const imageMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
      const imageGeom = new THREE.PlaneGeometry(defaultWidth, baseHeight)
      const imageMesh = new THREE.Mesh(imageGeom, imageMat)
      
      // 3号墙位置：x=-30, z=0，面向内部（+X方向）
      // 图片贴在墙面上，稍微前移避免共面
      imageMesh.position.set(-29.85, 3, 0)
      imageMesh.rotation.y = -Math.PI / 2 // 面向内部，修正朝向
      imageMesh.scale.x = -1 // 翻转镜像
      
      // 图片加载完成后调整尺寸保持原始比例
      const updateImageSize = () => {
        if (texture.image) {
          const imageAspectRatio = texture.image.width / texture.image.height
          const imageWidth = baseHeight * imageAspectRatio
          
          // 更新几何体尺寸
          imageGeom.dispose()
          const newImageGeom = new THREE.PlaneGeometry(imageWidth, baseHeight)
          imageMesh.geometry = newImageGeom
          
          console.log('在3号墙上添加alldzz.png图片，保持原始比例:', imageWidth, 'x', baseHeight)
        }
      }
      
      // 检查图片是否已经加载完成
      if (texture.image) {
        updateImageSize()
      } else {
        // 如果还没加载完成，等待加载完成
        const checkLoaded = () => {
          if (texture.image) {
            updateImageSize()
          } else {
            // 继续等待
            setTimeout(checkLoaded, 100)
          }
        }
        checkLoaded()
      }
      
      scene.add(imageMesh)
      console.log('在3号墙上添加alldzz.png图片（默认尺寸）')
    }

    // 在6号墙上添加jiaolianzhu.png图片
    {
      // 加载jiaolianzhu.png图片纹理
      const texture = new THREE.TextureLoader().load(jiaolianzhuImg)
      texture.colorSpace = THREE.SRGBColorSpace
      texture.anisotropy = 4
      
      // 设置一个默认尺寸，等图片加载完成后再调整
      const baseHeight = 6 // 适中高度
      const defaultWidth = 8 // 适中默认宽度
      
      const imageMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
      const imageGeom = new THREE.PlaneGeometry(defaultWidth, baseHeight)
      const imageMesh = new THREE.Mesh(imageGeom, imageMat)
      
      // 6号墙位置：x=-8, z=7.5，面向内部（+X方向）
      // 图片贴在墙面上，稍微前移避免共面
      imageMesh.position.set(-7.85, 3, 8.16)
      imageMesh.rotation.y = Math.PI // 面向内部
      imageMesh.scale.x = -1 // 翻转镜像
      
      // 设置用户数据用于交互检测
      imageMesh.userData.imageName = '教练组'
      imageMesh.userData.imageUrl = jiaolianzhuImg
      imageMesh.userData.interactionPosition = new THREE.Vector3(-7.85, 3, 8.16)
      
      // 图片加载完成后调整尺寸保持原始比例
      const updateImageSize = () => {
        if (texture.image) {
          const imageAspectRatio = texture.image.width / texture.image.height
          const imageWidth = baseHeight * imageAspectRatio
          
          // 更新几何体尺寸
          imageGeom.dispose()
          const newImageGeom = new THREE.PlaneGeometry(imageWidth, baseHeight)
          imageMesh.geometry = newImageGeom
          
          console.log('在6号墙上添加jiaolianzhu.png图片，保持原始比例:', imageWidth, 'x', baseHeight)
        }
      }
      
      // 检查图片是否已经加载完成
      if (texture.image) {
        updateImageSize()
      } else {
        // 如果还没加载完成，等待加载完成
        const checkLoaded = () => {
          if (texture.image) {
            updateImageSize()
          } else {
            // 继续等待
            setTimeout(checkLoaded, 100)
          }
        }
        checkLoaded()
      }
      
      scene.add(imageMesh)
      console.log('在6号墙上添加jiaolianzhu.png图片（默认尺寸）')
    }

    // 在7号墙上添加share_afcb133b8061cb6ef143eaebb2ec5c2c.png图片
    {
      // 加载share_afcb133b8061cb6ef143eaebb2ec5c2c.png图片纹理
      const texture = new THREE.TextureLoader().load(shareAfcbImg)
      texture.colorSpace = THREE.SRGBColorSpace
      texture.anisotropy = 4
      
      // 设置一个默认尺寸，等图片加载完成后再调整
      const baseHeight = 6 // 适中高度
      const defaultWidth = 8 // 适中默认宽度
      
      const imageMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
      const imageGeom = new THREE.PlaneGeometry(defaultWidth, baseHeight)
      const imageMesh = new THREE.Mesh(imageGeom, imageMat)
      
      // 7号墙位置：x=-8, z=-7.5，面向内部（+X方向）
      // 图片贴在墙面上，稍微前移避免共面
      imageMesh.position.set(-7.85, 3, -8.16)
      imageMesh.rotation.y = Math.PI // 面向内部
      
      // 设置用户数据用于交互检测
      imageMesh.userData.imageName = '球员合影'
      imageMesh.userData.imageUrl = shareAfcbImg
      imageMesh.userData.interactionPosition = new THREE.Vector3(-7.85, 3, -7.84)
      
      // 图片加载完成后调整尺寸保持原始比例
      const updateImageSize = () => {
        if (texture.image) {
          const imageAspectRatio = texture.image.width / texture.image.height
          const imageWidth = baseHeight * imageAspectRatio
          
          // 更新几何体尺寸
          imageGeom.dispose()
          const newImageGeom = new THREE.PlaneGeometry(imageWidth, baseHeight)
          imageMesh.geometry = newImageGeom
          
          console.log('在7号墙上添加share_afcb133b8061cb6ef143eaebb2ec5c2c.png图片，保持原始比例:', imageWidth, 'x', baseHeight)
        }
      }
      
      // 检查图片是否已经加载完成
      if (texture.image) {
        updateImageSize()
      } else {
        // 如果还没加载完成，等待加载完成
        const checkLoaded = () => {
          if (texture.image) {
            updateImageSize()
          } else {
            // 继续等待
            setTimeout(checkLoaded, 100)
          }
        }
        checkLoaded()
      }
      
      scene.add(imageMesh)
      console.log('在7号墙上添加share_afcb133b8061cb6ef143eaebb2ec5c2c.png图片（默认尺寸）')
    }

    // 在5号墙背后创建图片展示区域（13张图片带相框）
    {
      const imageList = [
        { img: dacImg, name: '吴昌泽',title: '#15 吴昌泽' },
        { img: dayaImg, name: 'daya',title: '#27 俞泽辰' },
        { img: ergeImg, name: 'erge',title: '#22 李晓旭' },
        { img: fuImg, name: 'fu',title: '#4 凯尔-弗格' },
        { img: fuhaoImg, name: 'fuhao',title: '#1 付豪' },
        { img: wugeImg, name: 'wuge',title: '教练员：乌戈-洛佩斯' },
        { img: yangmingImg, name: 'yangming',title: '教练员：杨鸣' },
        { img: wunaiqunImg, name: 'wunaiqun',title: '教练员：吴乃群' },
        { img: guo13Img, name: 'guo13',title: '#13 郭艾伦' },
        { img: shoudiImg, name: 'shoudi',title: '#36 鄢手骐' },
        { img: zhang77Img, name: 'zhang77',title: '#77 张镇麟' },
        { img: zhao3Img, name: 'zhao3',title: '#3 赵继伟' },
        { img: liu17Img, name: 'liu17',title: '#17 刘雁宇' }
      ]

      // 5号墙位置：x=8，图片贴在墙背后（x=8.2）
      const wallX = 8.2
      const startY = 3.0 // 起始高度（降低）
      const startZ = -13 // 起始Z位置
      
      // 布局参数：13张图片一行展示
      const cols = 13
      const spacingX = 2.2 // 列间距（进一步减小间距适应13张）
      const imageSize = 1.7 // 图片基准大小（再放大）
      const frameWidth = 0.12 // 相框宽度（稍微减小）

      // 相框材质
      const frameMaterial = new THREE.MeshStandardMaterial({ color: '#8B4513' }) // 棕色木质相框
      const backMaterial = new THREE.MeshStandardMaterial({ color: '#F5F5DC' }) // 米色背景

      imageList.forEach((item, index) => {
        const col = index % cols
        
        // 计算位置（一行展示）
        const x = wallX
        const y = startY // 固定高度，不换行
        const z = startZ + col * spacingX

        // 加载图片纹理
        const texture = new THREE.TextureLoader().load(item.img)
        texture.colorSpace = THREE.SRGBColorSpace
        texture.anisotropy = 4

        // 创建图片平面（保持原始比例）
        const updateImageSize = () => {
          if (texture.image) {
            const aspectRatio = texture.image.width / texture.image.height
            const imgWidth = imageSize * aspectRatio
            const imgHeight = imageSize

            // 创建图片材质和几何体
            const imageMat = new THREE.MeshBasicMaterial({ 
              map: texture, 
              transparent: true, 
              side: THREE.DoubleSide 
            })
            const imageGeom = new THREE.PlaneGeometry(imgWidth, imgHeight)
            const imageMesh = new THREE.Mesh(imageGeom, imageMat)
            
            // 创建相框（先添加背景层）
            const frameOuterWidth = imgWidth + frameWidth * 2
            const frameOuterHeight = imgHeight + frameWidth * 2
            
            // 相框内框（背景）- 最底层
            const innerGeom = new THREE.PlaneGeometry(imgWidth + 0.1, imgHeight + 0.1)
            const innerMesh = new THREE.Mesh(innerGeom, backMaterial)
            innerMesh.position.set(x + 0.005, y, z)
            innerMesh.rotation.y = Math.PI / 2 // 面向墙内（背后），修正镜像问题
            scene.add(innerMesh)
            
            // 相框外框 - 中间层
            const frameGeom = new THREE.PlaneGeometry(frameOuterWidth, frameOuterHeight)
            const frameMesh = new THREE.Mesh(frameGeom, frameMaterial)
            frameMesh.position.set(x + 0.01, y, z) // 稍微前移
            frameMesh.rotation.y = Math.PI / 2 // 面向墙内（背后），修正镜像问题
            scene.add(frameMesh)

            // 设置图片位置 - 最顶层
            imageMesh.position.set(x + 0.02, y, z) // 图片在最前面
            imageMesh.rotation.y = Math.PI / 2 // 面向墙内（背后），修正镜像问题
            scene.add(imageMesh)
            
            // 在图片下方添加title文字
            if (item.title) {
              const titleCanvas = document.createElement('canvas')
              titleCanvas.width = 512
              titleCanvas.height = 128
              const titleCtx = titleCanvas.getContext('2d')!
              
              // 设置文字样式
              titleCtx.fillStyle = '#000000' // 黑色文字
              titleCtx.strokeStyle = 'rgba(255,255,255,0.8)' // 白色描边
              titleCtx.lineWidth = 2
              titleCtx.textAlign = 'center'
              titleCtx.textBaseline = 'middle'
              titleCtx.font = 'bold 48px "Microsoft YaHei", "PingFang SC", Arial' // 更大的字体
              
              // 绘制文字
              titleCtx.strokeText(item.title, titleCanvas.width / 2, titleCanvas.height / 2)
              titleCtx.fillText(item.title, titleCanvas.width / 2, titleCanvas.height / 2)
              
              // 创建文字纹理
              const titleTexture = new THREE.CanvasTexture(titleCanvas)
              titleTexture.colorSpace = THREE.SRGBColorSpace
              titleTexture.needsUpdate = true
              
              // 创建文字材质
              const titleMaterial = new THREE.MeshBasicMaterial({ 
                map: titleTexture, 
                transparent: true,
                side: THREE.DoubleSide
              })
              
              // 创建文字平面
              const titleWidth = imgWidth // 文字宽度接近图片宽度
              const titleHeight = 0.6 // 更大的文字高度
              const titleGeometry = new THREE.PlaneGeometry(titleWidth, titleHeight)
              const titleMesh = new THREE.Mesh(titleGeometry, titleMaterial)
              
              // 设置文字位置（在图片下方，更靠近图片）
              titleMesh.position.set(x + 0.02, y - imgHeight/2 - titleHeight/2, z)
              titleMesh.rotation.y = Math.PI / 2 // 面向墙内
              
              scene.add(titleMesh)
            }

            console.log(`添加图片 ${item.name} 到5号墙背后，位置: (${x}, ${y}, ${z})`)
          }
        }

        // 检查图片是否已加载
        if (texture.image) {
          updateImageSize()
        } else {
          const checkLoaded = () => {
            if (texture.image) {
              updateImageSize()
            } else {
              setTimeout(checkLoaded, 100)
            }
          }
          checkLoaded()
        }
      })

      console.log('在5号墙背后创建13张图片展示区域')
    }

    // 在5号墙上方添加"球队个人荣誉墙"文字
    {
      // 创建文字Canvas
      const textCanvas = document.createElement('canvas')
      textCanvas.width = 4096 // 增加宽度以适应更大的字符间距
      textCanvas.height = 512
      const ctx = textCanvas.getContext('2d')!
      
      // 设置背景
      ctx.fillStyle = 'rgba(0,0,0,0)'
      ctx.fillRect(0, 0, textCanvas.width, textCanvas.height)
      
      // 设置文字样式
      ctx.fillStyle = '#ff0000' // 红色文字
      ctx.strokeStyle = 'rgba(0,0,0,0.8)'
      ctx.lineWidth = 8
      ctx.textAlign = 'center'
      ctx.textBaseline = 'middle'
      ctx.font = 'bold 180px "SimHei", "黑体", "Arial Black", sans-serif'
      
      // 绘制文字（增加字符间距）
      const text = '球队个人荣誉墙'
      const letterSpacing = 250 // 字符间距
      
      // 计算总宽度和起始位置
      const totalWidth = (text.length - 1) * letterSpacing
      const startX = (textCanvas.width - totalWidth) / 2
      
      for (let i = 0; i < text.length; i++) {
        const char = text[i]
        const x = startX + i * letterSpacing
        ctx.strokeText(char, x, textCanvas.height / 2)
        ctx.fillText(char, x, textCanvas.height / 2)
      }
      
      // 创建纹理
      const textTexture = new THREE.CanvasTexture(textCanvas)
      textTexture.colorSpace = THREE.SRGBColorSpace
      textTexture.needsUpdate = true
      
      // 创建材质
      const textMaterial = new THREE.MeshBasicMaterial({ 
        map: textTexture, 
        transparent: true,
        side: THREE.DoubleSide
      })
      
      // 创建文字平面
      const textWidth = 20 // 增加宽度以适应更大的字符间距
      const textHeight = 3
      const textGeometry = new THREE.PlaneGeometry(textWidth, textHeight)
      const textMesh = new THREE.Mesh(textGeometry, textMaterial)
      
      // 设置位置（在5号墙上方）
      textMesh.position.set(8.2, 5.5, 0) // 稍微前移，避免与墙共面
      textMesh.rotation.y = Math.PI / 2 // 面向墙内
      
      scene.add(textMesh)
      
      console.log('在5号墙上方添加"球队个人荣誉墙"文字')
    }

    // 在5号墙上面添加4张冠军海报（无边框）
    {
      const championList = [
        { img: champion2017Img, name: '2017-2018' },
        { img: champion2021Img, name: '2021-2022' },
        { img: champion2022Img, name: '2022-2023' },
        { img: champion2023Img, name: '2023-2024' }
      ]

      // 5号墙位置：x=8，图片贴在墙上面（x=8.2）
      const wallX = 7.8
      const startY = 6.4 // 起始高度（在文字上方）
      const startZ = -4.5 // 起始Z位置
      
      // 布局参数：4张图片一行展示
      const cols = 4
      const spacingX = 3.0 // 列间距
      const imageSize = 3.0 // 图片基准大小（放大）

      championList.forEach((item, index) => {
        const col = index % cols
        
        // 计算位置（一行展示）
        const x = wallX
        const y = startY
        const z = startZ + col * spacingX

        // 加载图片纹理
        const texture = new THREE.TextureLoader().load(item.img)
        texture.colorSpace = THREE.SRGBColorSpace
        texture.anisotropy = 4

        // 创建图片平面（保持原始比例）
        const updateImageSize = () => {
          if (texture.image) {
            const aspectRatio = texture.image.width / texture.image.height
            const imgWidth = imageSize * aspectRatio
            const imgHeight = imageSize

            // 创建图片材质和几何体
            const imageMat = new THREE.MeshBasicMaterial({ 
              map: texture, 
              transparent: true, 
              side: THREE.DoubleSide 
            })
            const imageGeom = new THREE.PlaneGeometry(imgWidth, imgHeight)
            const imageMesh = new THREE.Mesh(imageGeom, imageMat)
            
            // 设置图片位置
            imageMesh.position.set(x, y, z)
            imageMesh.rotation.y = -Math.PI / 2 // 面向墙内，修正方向
            
            scene.add(imageMesh)
            console.log(`添加冠军海报 ${item.name} 到5号墙上面，位置: (${x}, ${y}, ${z})`)
          }
        }

        // 检查图片是否已加载
        if (texture.image) {
          updateImageSize()
        } else {
          const checkLoaded = () => {
            if (texture.image) {
              updateImageSize()
            } else {
              setTimeout(checkLoaded, 100)
            }
          }
          checkLoaded()
        }
      })

      console.log('在5号墙上面创建4张冠军海报展示区域')
    }

    // 天花板已删除，让太阳光照射进来

    // 多个房间的装饰
    // 主厅水晶吊灯（已删除）
    // const mainChandelierGroup = new THREE.Group()
    // mainChandelierGroup.position.set(0, 7, 0)
    // const chandelierGeometry = new THREE.CylinderGeometry(0.5, 0.8, 1)
    // const chandelierMaterial = new THREE.MeshStandardMaterial({ color: '#ffd700', emissive: '#ffd700', emissiveIntensity: 0.3 })
    // const chandelier = new THREE.Mesh(chandelierGeometry, chandelierMaterial)
    // chandelier.position.set(0, -0.5, 0)
    // mainChandelierGroup.add(chandelier)
    // for (let i = 0; i < 8; i++) {
    //   const crystalGeometry = new THREE.SphereGeometry(0.1)
    //   const crystalMaterial = new THREE.MeshStandardMaterial({ color: '#ffffff', transparent: true, opacity: 0.8 })
    //   const crystal = new THREE.Mesh(crystalGeometry, crystalMaterial)
    //   crystal.position.set(
    //     Math.cos(i * Math.PI / 4) * 1.2,
    //     -0.5 + Math.sin(i * Math.PI / 4) * 0.3,
    //     Math.sin(i * Math.PI / 4) * 1.2
    //   )
    //   mainChandelierGroup.add(crystal)
    // }
    // scene.add(mainChandelierGroup)

    // 左右房间吊灯已删除

    // 展示台已删除

    // 大厅前台（简约风）
    {
      const counterMat = new THREE.MeshStandardMaterial({ color: '#ffffff' })
      const toeMat = new THREE.MeshStandardMaterial({ color: '#cccccc' })
      const topMat = new THREE.MeshStandardMaterial({ color: '#2c3e50' })

      // 主体台体（略弧形可后续替换为曲面，这里先用矩形组合）
      const bodyGeom = new THREE.BoxGeometry(6.2, 1.1, 1.6)
      const body = new THREE.Mesh(bodyGeom, counterMat)
      body.position.set(5, 0.55, 0)
      body.rotation.y = Math.PI / 2 // 左转90°，朝向 -Z
      scene.add(body)

      // 上台面
      const topGeom = new THREE.BoxGeometry(6.4, 0.08, 1.8)
      const top = new THREE.Mesh(topGeom, topMat)
      top.position.set(5, 1.14, 0)
      top.rotation.y = Math.PI / 2
      scene.add(top)

      // 踢脚线
      const toeGeom = new THREE.BoxGeometry(6.2, 0.1, 1.6)
      const toe = new THREE.Mesh(toeGeom, toeMat)
      toe.position.set(5, 0.05, 0)
      toe.rotation.y = Math.PI / 2
      scene.add(toe)

      // ——— 前台装饰：两个黑色屏幕（偏左）、小台灯、盆栽、收纳盒 ———
      {
        // 参考位置：桌面中心 (5, 1.14, 0)，桌长沿 z（±3.1），桌深沿 x（±0.9）
        const deskCenterX = 5
        const deskTopY = 1.14
        const deskCenterZ = 0

        // 1) 两个黑色屏幕（偏左）
        const screenMat = new THREE.MeshStandardMaterial({ color: '#111111' })
        const bezelMat = new THREE.MeshStandardMaterial({ color: '#000000' })
        const baseMat = new THREE.MeshStandardMaterial({ color: '#333333' })
        const panelGeom = new THREE.BoxGeometry(0.8, 0.5, 0.03)
        const baseGeom = new THREE.BoxGeometry(0.35, 0.02, 0.25)
        const stemGeom = new THREE.BoxGeometry(0.03, 0.15, 0.03)

        const placeMonitor = (offsetZ: number) => {
          const x = deskCenterX - 0.3 // 偏左（面向大厅时）
          const z = deskCenterZ + offsetZ
          const y = deskTopY + 0.25
          const panel = new THREE.Mesh(panelGeom, screenMat)
          panel.position.set(x, y, z)
          panel.rotation.y = Math.PI / 2 // 面向大厅一侧
          scene.add(panel)
          const stem = new THREE.Mesh(stemGeom, bezelMat)
          stem.position.set(x, deskTopY + 0.12, z)
          scene.add(stem)
          const base = new THREE.Mesh(baseGeom, baseMat)
          base.position.set(x, deskTopY + 0.02, z)
          scene.add(base)
        }
        placeMonitor(-1.5)
        placeMonitor(-0.5)

        // 2) 小台灯（带微弱点光源）
        const lampBaseGeom = new THREE.CylinderGeometry(0.08, 0.08, 0.02, 16)
        const lampRodGeom = new THREE.CylinderGeometry(0.02, 0.02, 0.18, 12)
        const lampShadeGeom = new THREE.ConeGeometry(0.12, 0.18, 16)
        const lampMat = new THREE.MeshStandardMaterial({ color: '#dddddd' })
        const shadeMat = new THREE.MeshStandardMaterial({ color: '#ffffff', emissive: '#ffffff', emissiveIntensity: 0.2 })
        const lampX = deskCenterX + 0.25
        const lampZ = deskCenterZ + 0.6
        const base = new THREE.Mesh(lampBaseGeom, lampMat)
        base.position.set(lampX, deskTopY + 0.01, lampZ)
        scene.add(base)
        const rod = new THREE.Mesh(lampRodGeom, lampMat)
        rod.position.set(lampX, deskTopY + 0.11, lampZ)
        scene.add(rod)
        const shade = new THREE.Mesh(lampShadeGeom, shadeMat)
        shade.position.set(lampX, deskTopY + 0.28, lampZ)
        shade.rotation.x = Math.PI // 灯罩朝下
        scene.add(shade)
        const lampLight = new THREE.PointLight('#fff7e6', 0.5, 2)
        lampLight.position.set(lampX, deskTopY + 0.28, lampZ)
        scene.add(lampLight)

        // 3) 小盆栽
        const potGeom = new THREE.CylinderGeometry(0.08, 0.1, 0.08, 16)
        const potMat = new THREE.MeshStandardMaterial({ color: '#b5651d' })
        const plantGeom = new THREE.SphereGeometry(0.12, 16, 12)
        const plantMat = new THREE.MeshStandardMaterial({ color: '#2e8b57' })
        const pot = new THREE.Mesh(potGeom, potMat)
        pot.position.set(deskCenterX - 0.15, deskTopY + 0.04, deskCenterZ + 1.4)
        scene.add(pot)
        const plant = new THREE.Mesh(plantGeom, plantMat)
        plant.position.set(deskCenterX - 0.15, deskTopY + 0.18, deskCenterZ + 1.4)
        scene.add(plant)

        // 4) 收纳盒
        const boxGeom = new THREE.BoxGeometry(0.35, 0.12, 0.25)
        const boxMat = new THREE.MeshStandardMaterial({ color: '#cfcfcf' })
        const box = new THREE.Mesh(boxGeom, boxMat)
        box.position.set(deskCenterX + 0.35, deskTopY + 0.06, deskCenterZ + 2.2)
        scene.add(box)
      }

      // ——— 前台正面 Logo ———
      {
        // 加载纹理
        const texture = new THREE.TextureLoader().load(logoImg)
        texture.colorSpace = THREE.SRGBColorSpace
        texture.anisotropy = 4
        const logoMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide })
        // 估算尺寸（宽×高）并保持居中，贴在顾客侧前板上
        const logoW = 1.4
        const logoH = 0.8
        const logoGeom = new THREE.PlaneGeometry(logoW, logoH)
        const logo = new THREE.Mesh(logoGeom, logoMat)
        // desk front 在 +X 侧：让平面朝 +X（旋转 -90° 绕 Y），并略微前移避免共面
        logo.rotation.y = -Math.PI / 2
        logo.position.set(4.1, 0.6, 0)
        scene.add(logo)

        // 5号墙（主垂直墙，x≈8）上的同款 Logo：略微内缩避免与墙共面
        const wallLogoGeom = new THREE.PlaneGeometry(logoW * 2.6, logoH * 2.6)
        const wallLogo = new THREE.Mesh(wallLogoGeom, logoMat)
        wallLogo.position.set(29.8, 3, 0)
        // 面向 -X（朝向大厅/前台）
        wallLogo.rotation.y = -Math.PI / 2
        scene.add(wallLogo)

        // 5号墙文字（Canvas 文本贴图）- 方案A
        const textCanvas = document.createElement('canvas')
        textCanvas.width = 3048
        textCanvas.height = 512
        const ctx = textCanvas.getContext('2d')!
        ctx.clearRect(0, 0, textCanvas.width, textCanvas.height)
        ctx.fillStyle = 'rgba(0,0,0,0)'
        ctx.fillRect(0, 0, textCanvas.width, textCanvas.height)
        // 文本样式
        ctx.fillStyle = '#ffffff'
        ctx.strokeStyle = 'rgba(0,0,0,0.4)'
        ctx.lineWidth = 6
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        ctx.font = 'bold 220px "Microsoft YaHei", "PingFang SC", Arial'
        const text = '辽宁本钢'
        // 预留左右边距，避免贴边裁切
        const cx = textCanvas.width / 2
        const cy = textCanvas.height / 2
        ctx.strokeText(text, cx, cy)
        ctx.fillText(text, cx, cy)
        const textTex = new THREE.CanvasTexture(textCanvas)
        textTex.colorSpace = THREE.SRGBColorSpace
        textTex.needsUpdate = true
        const textMat = new THREE.MeshBasicMaterial({ map: textTex, transparent: true })
        const textW = 16.0
        const textH = 2.8
        const textGeom = new THREE.PlaneGeometry(textW, textH)
        const textMesh = new THREE.Mesh(textGeom, textMat)
        // 放在墙面中段，logo 下方区域
        textMesh.position.set(7.5, 3, 0)
        textMesh.rotation.y = -Math.PI / 2
        // 背景底色平面（略大并略微内移避免共面）
        const pad = 0.3
        const bgGeom1 = new THREE.PlaneGeometry(textW + pad * 2, textH + pad * 2)
        const bgMat1 = new THREE.MeshBasicMaterial({ color: '#3a5964', transparent: true, opacity: 0.35 })
        const bg1 = new THREE.Mesh(bgGeom1, bgMat1)
        bg1.position.set(textMesh.position.x + 0.02, textMesh.position.y, textMesh.position.z)
        bg1.rotation.y = textMesh.rotation.y
        scene.add(bg1)
        scene.add(textMesh)

        // 新增一行：欢迎光临（位于现有文字上方，居中）
        const textCanvas2 = document.createElement('canvas')
        textCanvas2.width = 3048
        textCanvas2.height = 512
        const ctx2 = textCanvas2.getContext('2d')!
        ctx2.clearRect(0, 0, textCanvas2.width, textCanvas2.height)
        ctx2.fillStyle = 'rgba(0,0,0,0)'
        ctx2.fillRect(0, 0, textCanvas2.width, textCanvas2.height)
        ctx2.fillStyle = '#ffffff'
        ctx2.strokeStyle = 'rgba(0,0,0,0.4)'
        ctx2.lineWidth = 6
        ctx2.textAlign = 'center'
        ctx2.textBaseline = 'middle'
        ctx2.font = 'bold 200px "Microsoft YaHei", "PingFang SC", Arial'
        const text2 = '辽宁沈阳三生飞豹篮球俱乐部'
        ctx2.strokeText(text2, textCanvas2.width / 2, textCanvas2.height / 2)
        ctx2.fillText(text2, textCanvas2.width / 2, textCanvas2.height / 2)
        const textTex2 = new THREE.CanvasTexture(textCanvas2)
        textTex2.colorSpace = THREE.SRGBColorSpace
        textTex2.needsUpdate = true
        const textMat2 = new THREE.MeshBasicMaterial({ map: textTex2, transparent: true })
        const textW2 = 18.0
        const textH2 = 3
        const textGeom2 = new THREE.PlaneGeometry(textW2, textH2)
        const textMesh2 = new THREE.Mesh(textGeom2, textMat2)
        textMesh2.position.set(-15.50, 6.2, 0)
        textMesh2.rotation.y = -Math.PI / 2
        // 背景底色平面（略大并略微内移避免共面）
        const bgGeom2 = new THREE.PlaneGeometry(textW2 + 0.3 * 2, textH2 + 0.3 * 2)
        const bgMat2 = new THREE.MeshBasicMaterial({ color: '#3a5964', transparent: true, opacity: 0.35 })
        const bg2 = new THREE.Mesh(bgGeom2, bgMat2)
        bg2.position.set(textMesh2.position.x + 0.02, textMesh2.position.y, textMesh2.position.z)
        bg2.rotation.y = textMesh2.rotation.y
        scene.add(bg2)
        scene.add(textMesh2)
        // 背面可读：添加反向镜像文字平面与背景
        const textMat2Back = textMat2.clone()
        textMat2Back.side = THREE.DoubleSide
        const textMesh2Back = new THREE.Mesh(textGeom2, textMat2Back)
        textMesh2Back.position.set(textMesh2.position.x - 0.02, textMesh2.position.y, textMesh2.position.z)
        textMesh2Back.rotation.y = Math.PI / 2
        textMesh2Back.scale.x = -1 // 镜像
        scene.add(textMesh2Back)
        const bgMat2Back = bgMat2.clone()
        bgMat2Back.side = THREE.DoubleSide
        const bg2Back = new THREE.Mesh(bgGeom2, bgMat2Back)
        bg2Back.position.set(textMesh2Back.position.x - 0.02, textMesh2Back.position.y, textMesh2Back.position.z)
        bg2Back.rotation.y = textMesh2Back.rotation.y
        scene.add(bg2Back)

        // 3D 浮雕字已移除，仅保留平面文字
      }
    }

    // 装饰性雕塑 - 主厅中央（已删除）
    // const sculptureGeometry = new THREE.TorusGeometry(1.5, 0.4, 16, 32)
    // const sculptureMaterial = new THREE.MeshStandardMaterial({ color: '#c0c0c0' })
    // const sculpture = new THREE.Mesh(sculptureGeometry, sculptureMaterial)
    // sculpture.position.set(0, 1.5, 0)
    // scene.add(sculpture)

    // 画框已删除

    // 房间地毯
    const carpetMaterial = new THREE.MeshStandardMaterial({ color: '#8b0000' })
    
    // 主厅地毯
    const mainCarpetGeometry = new THREE.BoxGeometry(12, 0.05, 12)
    const mainCarpet = new THREE.Mesh(mainCarpetGeometry, carpetMaterial)
    mainCarpet.position.set(0, 0.025, 0)
    scene.add(mainCarpet)

    // 左侧房间地毯
    const leftCarpetGeometry = new THREE.BoxGeometry(12, 0.05, 8)
    const leftCarpet = new THREE.Mesh(leftCarpetGeometry, carpetMaterial)
    leftCarpet.position.set(-20, 0.025, 0)
    scene.add(leftCarpet)

    // 右侧房间地毯
    const rightCarpetGeometry = new THREE.BoxGeometry(15, 0.05, 8)
    const rightCarpet = new THREE.Mesh(rightCarpetGeometry, carpetMaterial)
    rightCarpet.position.set(25, 0.025, 0)
    scene.add(rightCarpet)
 
    // 前台两侧大型盆栽
    {
      const makeBigPlanter = (x: number, z: number, scale = 1.0) => {
        const group = new THREE.Group()
        group.position.set(x, 0, z)
        group.scale.set(scale, scale, scale)
        scene.add(group)
        // 盆器：拉丝金属大圆柱
        const potOuterGeom = new THREE.CylinderGeometry(0.55, 0.55, 0.9, 32)
        const potOuterMat = new THREE.MeshStandardMaterial({ color: '#b5a27a', metalness: 0.75, roughness: 0.25 })
        const pot = new THREE.Mesh(potOuterGeom, potOuterMat)
        pot.position.set(0, 0.45, 0)
        group.add(pot)

        const rimGeom = new THREE.TorusGeometry(0.55, 0.03, 16, 64)
        const rimMat = new THREE.MeshStandardMaterial({ color: '#d8c69a', metalness: 0.85, roughness: 0.2 })
        const rim = new THREE.Mesh(rimGeom, rimMat)
        rim.position.set(0, 0.9, 0)
        rim.rotation.x = Math.PI / 2
        group.add(rim)

        // 植株：高大型棕榈（简化版叶簇）
        const leafMat = new THREE.MeshStandardMaterial({ color: '#2e8656', roughness: 0.6 })
        const leafGeom = new THREE.ConeGeometry(0.07, 1.6, 8)
        for (let i = 0; i < 28; i++) {
          const leaf = new THREE.Mesh(leafGeom, leafMat)
          const ang = (i / 18) * Math.PI * 2
          const radius = 0.22 + Math.random() * 0.12
          leaf.position.set(Math.cos(ang) * radius, 1.8 + Math.random() * 0.2, Math.sin(ang) * radius)
          leaf.rotation.z = (Math.random() * 0.4) + 0.7
          leaf.rotation.y = ang
          group.add(leaf)
        }

        // 上照灯
        const uplight = new THREE.SpotLight('#ffd7a1', 1.3, 7, Math.PI / 5, 0.4)
        uplight.position.set(0, 0.1, 0)
        uplight.target.position.set(0, 2.3, 0)
        group.add(uplight)
        group.add(uplight.target)
      }
      makeBigPlanter(5, -4.6)
      makeBigPlanter(5, 4.6)
      // 四处更大的盆栽（scale=1.4）
      makeBigPlanter(6.5, 10, 1.4)
      makeBigPlanter(6.5, 13, 1.4)
      makeBigPlanter(6.5, -10, 1.4)
      makeBigPlanter(6.5, -13, 1.4)
    }
 
    // 会议室：木纹长方桌（8×3×0.75），在 8/10 号墙所在房间居中，长边沿 x 方向
    {
      // 长边沿 x：x=8, z=3
      const tableTopGeom = new THREE.BoxGeometry(8, 0.1, 3)
      const tableTopMat = new THREE.MeshStandardMaterial({ color: '#8b5a2b' })
      const tableTop = new THREE.Mesh(tableTopGeom, tableTopMat)
      // 房间在 x∈[8,30], z∈[-8,8]，中心约 (x≈22.55, z=0)
      tableTop.position.set(22.55, 0.85, 0)
      tableTop.castShadow = true
      tableTop.receiveShadow = true
      scene.add(tableTop)
 
      // 四个桌腿
      const legGeom = new THREE.BoxGeometry(0.15, 0.8, 0.15)
      const legMat = new THREE.MeshStandardMaterial({ color: '#6b4423' })
      // 半长4、半宽1.5；腿位置略内缩：x≈±3.7, z≈±1.35
      const legOffsets = [
        [-3.7, 0.4, -1.35], [3.7, 0.4, -1.35], [-3.7, 0.4, 1.35], [3.7, 0.4, 1.35]
      ]
      legOffsets.forEach(([lx, ly, lz]) => {
        const leg = new THREE.Mesh(legGeom, legMat)
        leg.position.set(22.55 + lx, ly, lz)
        leg.castShadow = true
        scene.add(leg)
      })
 
      // 桌子碰撞将在运动控制模块中统一管理（此处不直接操作数组，避免作用域错误）
    }

    // 会议椅：20 把黑色靠背椅，围绕桌子摆放（长边各8把，首尾各2把）
    {
      const chairSeatGeom = new THREE.BoxGeometry(0.5, 0.05, 0.5)
      const chairBackGeom = new THREE.BoxGeometry(0.5, 0.7, 0.05)
      const chairLegGeom = new THREE.BoxGeometry(0.05, 0.45, 0.05)
      const chairMat = new THREE.MeshStandardMaterial({ color: '#222222' })

      const centerX = 22.55
      const centerZ = 0
      const halfLen = 4 // 桌半长
      const halfWid = 1.5 // 桌半宽
      const chairOffsetFromTable = 0.7 // 椅子离桌边距离，留出走动空间

      const addChair = (x: number, z: number, faceToX: number, faceToZ: number) => {
        // 座面
        const seat = new THREE.Mesh(chairSeatGeom, chairMat)
        seat.position.set(x, 0.45, z)
        scene.add(seat)
        // 靠背（朝向桌子）
        const back = new THREE.Mesh(chairBackGeom, chairMat)
        back.position.set(x - faceToZ * 0, 0.9, z - faceToX * 0) // 先放中心
        // 根据朝向把靠背从座面后移
        back.position.x += faceToX * 0
        back.position.z += faceToZ * -0.25
        scene.add(back)
        // 四个椅腿
        const legs: [number, number][] = [[-0.22, -0.22], [0.22, -0.22], [-0.22, 0.22], [0.22, 0.22]]
        legs.forEach(([dx, dz]) => {
          const leg = new THREE.Mesh(chairLegGeom, chairMat)
          leg.position.set(x + dx, 0.225, z + dz)
          scene.add(leg)
        })
      }

      // 长边：沿 x 方向均匀分布 8 把（两侧）
      const longSideCount = 8
      for (let i = 0; i < longSideCount; i++) {
        const t = (i + 1) / (longSideCount + 1)
        const px = centerX - halfLen + t * (halfLen * 2)
        // 上侧（+z）
        addChair(px, centerZ + halfWid + chairOffsetFromTable, 0, -1)
        // 下侧（-z）
        addChair(px, centerZ - halfWid - chairOffsetFromTable, 0, 1)
      }

      // 两个短边：各 1 把，靠近中心（首尾）
      addChair(centerX - halfLen - chairOffsetFromTable, centerZ, 1, 0)
      addChair(centerX + halfLen + chairOffsetFromTable, centerZ, -1, 0)
    }

    // 会议区地毯（深灰，覆盖桌子外扩 1m 范围）
    {
      const carpetGeom = new THREE.BoxGeometry(10, 0.02, 5)
      const carpetMat = new THREE.MeshStandardMaterial({ color: '#333333' })
      const carpet = new THREE.Mesh(carpetGeom, carpetMat)
      carpet.position.set(22.55, 0.01, 0)
      carpet.receiveShadow = true
      scene.add(carpet)
    }

    // 会议区照明：顶部线性灯 + 筒灯
    {
      // 线性灯（长条形发光体）
      const barGeom = new THREE.BoxGeometry(6, 0.05, 0.2)
      const barMat = new THREE.MeshStandardMaterial({ color: '#ffffff', emissive: '#ffffff', emissiveIntensity: 2.5 })
      const bar = new THREE.Mesh(barGeom, barMat)
      bar.position.set(22.55, 7.5, 0)
      scene.add(bar)

      // 两个筒灯（点光源模拟）
      const down1 = new THREE.SpotLight('#ffffff', 1.2, 12, Math.PI / 6, 0.3)
      down1.position.set(22.55 - 2, 7.2, 0)
      scene.add(down1)
      const down2 = new THREE.SpotLight('#ffffff', 1.2, 12, Math.PI / 6, 0.3)
      down2.position.set(22.55 + 2, 7.2, 0)
      scene.add(down2)
    }

    // 恢复 11/12 号墙为独立可见墙体（移除整面隔断）并补齐中间段
    {
      const accentMat = new THREE.MeshStandardMaterial({ color: '#d0d0d0' })
      // 11 号墙：小走廊墙，x≈15.1，z∈[-16,-8]
      const wall11Geom = new THREE.BoxGeometry(0.2, 8, 8)
      const wall11 = new THREE.Mesh(wall11Geom, accentMat)
      wall11.position.set(15.1, 4, -12)
      scene.add(wall11)
      // 12 号墙：与 11 相对上方，z∈[8,16]
      const wall12Geom = new THREE.BoxGeometry(0.2, 8, 8)
      const wall12 = new THREE.Mesh(wall12Geom, accentMat)
      wall12.position.set(15.1, 4, 12)
      scene.add(wall12)
      // 中间段：x≈15.1，z∈[-8,8]；两侧留门洞（z∈[-7.4,-5.6] 与 [5.6,7.4]）
      // 下边缘条：覆盖 z ∈ [-8, -7.4]
      const midLowEdgeGeom = new THREE.BoxGeometry(0.2, 8, 0.6)
      const midLowEdge = new THREE.Mesh(midLowEdgeGeom, accentMat)
      midLowEdge.position.set(15.1, 4, -7.7)
      scene.add(midLowEdge)
      // 中央实体：覆盖 z ∈ [-5.6, 5.6]
      const midCenterGeom = new THREE.BoxGeometry(0.2, 8, 11.2)
      const midCenter = new THREE.Mesh(midCenterGeom, accentMat)
      midCenter.position.set(15.1, 4, 0)
      scene.add(midCenter)
      // 上边缘条：覆盖 z ∈ [7.4, 8]
      const midHighEdgeGeom = new THREE.BoxGeometry(0.2, 8, 0.6)
      const midHighEdge = new THREE.Mesh(midHighEdgeGeom, accentMat)
      midHighEdge.position.set(15.1, 4, 7.7)
      scene.add(midHighEdge)
    }

    // 中央墙面大屏幕（支持占位黑屏 + 可选视频纹理）
    {
      // 可选视频路径：使用外链视频
      const videoSrc: string = 'https://stream7.iqilu.com/10339/upload_transcode/202002/09/20200209105011F0zPoYzHry.mp4'

      // 屏幕尺寸（宽×高），默认 16:9 比例
      const screenWidth = 8
      const screenHeight = 4.5
      const screenGeom = new THREE.PlaneGeometry(screenWidth, screenHeight)

      let screenMat: THREE.Material
      const disposeFns: Array<() => void> = []

      if (videoSrc) {
        const video = document.createElement('video')
        video.src = videoSrc
        video.crossOrigin = 'anonymous'
        video.loop = true
        video.muted = false // 期望默认不静音
        video.volume = 0 // 初始静音，进入会议室后再按距离调整
        video.autoplay = true
        video.playsInline = true
        meetingVideoRef.current = video
        // 尝试直接带声播放；若被浏览器拦截，则回退为静音播放并在首次点击后恢复声音
        const applyInitialVolume = () => {
          // 进入可播放状态后立刻依据当前位置设置音量
          const cam = camera
          const inRoom = cam.position.x >= 8 && cam.position.x <= 30 &&
                         cam.position.z >= -8 && cam.position.z <= 8
          if (inRoom) {
            const dx = cam.position.x - 22.55
            const dz = cam.position.z - 0
            const dist = Math.sqrt(dx*dx + dz*dz)
            const vol = Math.max(0, Math.min(1, 1 - dist / 14))
            video.volume = vol
            meetingVolumeRef.current = vol
          } else {
            video.volume = 0
            meetingVolumeRef.current = 0
          }
        }

        video.play().catch(() => {
          video.muted = true
          video.play().finally(() => {
            const enableSound = () => { video.muted = false; video.play().catch(() => {}) }
            document.addEventListener('click', enableSound, { once: true })
            disposeFns.push(() => document.removeEventListener('click', enableSound))
          })
        })

        video.addEventListener('canplay', applyInitialVolume)
        disposeFns.push(() => video.removeEventListener('canplay', applyInitialVolume))

        const videoTexture = new THREE.VideoTexture(video)
        videoTexture.colorSpace = THREE.SRGBColorSpace
        videoTexture.minFilter = THREE.LinearFilter
        videoTexture.magFilter = THREE.LinearFilter
        videoTexture.wrapS = THREE.ClampToEdgeWrapping
        videoTexture.wrapT = THREE.ClampToEdgeWrapping
        screenMat = new THREE.MeshBasicMaterial({ map: videoTexture, side: THREE.DoubleSide })

        disposeFns.push(() => { video.pause(); meetingVideoRef.current = null })
        disposeFns.push(() => { videoTexture.dispose() })
      } else {
        // 黑色占位屏
        screenMat = new THREE.MeshBasicMaterial({ color: '#000000', side: THREE.DoubleSide })
      }

      const screen = new THREE.Mesh(screenGeom, screenMat)
      // 安装在中央墙面前侧（避开墙体厚度），略微前移避免共面
      screen.position.set(15.22, 3.0, 0)
      screen.rotation.y = Math.PI / 2
      scene.add(screen)

      // 边框（略大 0.12），浅灰
      const frameGeom = new THREE.PlaneGeometry(screenWidth + 0.12, screenHeight + 0.12)
      const frameMat = new THREE.MeshBasicMaterial({ color: '#00ff66', side: THREE.DoubleSide })
      const frame = new THREE.Mesh(frameGeom, frameMat)
      frame.position.copy(screen.position)
      frame.rotation.copy(screen.rotation)
      scene.add(frame)
      // 屏幕再往外推出一点避免共面
      screen.position.x += 0.01

      // 清理
      const cleanupScreen = () => {
        scene.remove(screen)
        scene.remove(frame)
        screenGeom.dispose()
        frameGeom.dispose()
        if (screen.material instanceof THREE.Material) screen.material.dispose()
        disposeFns.forEach(fn => fn())
      }
      cleanups.push(cleanupScreen)
    }

    return () => {
      // 清理资源
      cleanups.forEach(fn => { fn() })
      scene.clear()
    }
  }, [scene, camera])

  // 距离音量控制：仅在进入会议室范围内才听到视频声音
  useFrame(() => {
    const video = meetingVideoRef.current
    if (!video) return
    const inRoom = camera.position.x >= 8 && camera.position.x <= 30 &&
                   camera.position.z >= -8 && camera.position.z <= 8
    if (inRoom) {
      const dx = camera.position.x - 22.55
      const dz = camera.position.z - 0
      const dist = Math.sqrt(dx*dx + dz*dz)
      const vol = Math.max(0, Math.min(1, 1 - dist / 14))
      if (Math.abs(vol - meetingVolumeRef.current) > 0.02) {
        video.volume = vol
        meetingVolumeRef.current = vol
      }
    } else if (meetingVolumeRef.current !== 0) {
      video.volume = 0
      meetingVolumeRef.current = 0
    }
  })

  return null
}

// 照明组件
const Lighting: React.FC<{ enabled: boolean }> = ({ enabled }) => {
  const { scene } = useThree()
  const lightsRef = useRef<THREE.Light[]>([])

  useEffect(() => {

    // 主厅聚光灯
    const mainLight = new THREE.SpotLight('#ffffff', 2, 50, Math.PI / 3, 0.5)
    mainLight.position.set(0, 7, 0)
    mainLight.castShadow = true
    mainLight.shadow.mapSize.width = 2048
    mainLight.shadow.mapSize.height = 2048
    scene.add(mainLight)
    lightsRef.current.push(mainLight)

    // 左侧房间聚光灯
    const leftLight = new THREE.SpotLight('#ffffff', 1.5, 30, Math.PI / 3, 0.5)
    leftLight.position.set(-15, 7, 0)
    leftLight.castShadow = true
    scene.add(leftLight)
    lightsRef.current.push(leftLight)

    // 右侧房间聚光灯
    const rightLight = new THREE.SpotLight('#ffffff', 1.5, 30, Math.PI / 3, 0.5)
    rightLight.position.set(25, 7, 0)
    rightLight.castShadow = true
    scene.add(rightLight)
    lightsRef.current.push(rightLight)

    // 增强的环境光 - 模拟天空光
    const ambientLight = new THREE.AmbientLight('#87CEEB', 0.8) // 天蓝色，更亮
    scene.add(ambientLight)
    lightsRef.current.push(ambientLight)

    // 太阳光 - 从上方照射
    const sunLight = new THREE.DirectionalLight('#FFE4B5', 2.0) // 温暖的太阳光
    sunLight.position.set(0, 20, 0) // 从正上方照射
    sunLight.target.position.set(0, 0, 0) // 照射到场景中心
    sunLight.castShadow = true
    sunLight.shadow.mapSize.width = 2048
    sunLight.shadow.mapSize.height = 2048
    sunLight.shadow.camera.near = 0.5
    sunLight.shadow.camera.far = 50
    sunLight.shadow.camera.left = -25
    sunLight.shadow.camera.right = 25
    sunLight.shadow.camera.top = 25
    sunLight.shadow.camera.bottom = -25
    scene.add(sunLight)
    scene.add(sunLight.target)
    lightsRef.current.push(sunLight)

    // 墙面装饰照明
    const wallLightPositions = [
      [-25, 6, 0], [25, 6, 0], [0, 6, -15], [0, 6, 15]
    ]
    
    wallLightPositions.forEach(pos => {
      const wallLight = new THREE.PointLight('#ffd700', 0.8, 20)
      wallLight.position.set(pos[0], pos[1], pos[2])
      scene.add(wallLight)
      lightsRef.current.push(wallLight)
    })

    // 展示台专用照明
    const pedestalLightPositions = [
      // 主厅展示台
      [-5, 3, 5], [5, 3, 5], [-5, 3, -5], [5, 3, -5],
      // 左侧房间展示台
      [-20, 3, 12], [-20, 3, -12],
      // 右侧房间展示台
      [25, 3, 12], [25, 3, -12], [25, 3, 0]
    ]
    
    pedestalLightPositions.forEach(pos => {
      const pedestalLight = new THREE.SpotLight('#ffffff', 1.2, 15, Math.PI / 4, 0.3)
      pedestalLight.position.set(pos[0], pos[1], pos[2])
      pedestalLight.target.position.set(pos[0], 0.5, pos[2])
      scene.add(pedestalLight)
      scene.add(pedestalLight.target)
      lightsRef.current.push(pedestalLight)
    })

    // 走廊照明
    const corridorLight = new THREE.PointLight('#ffa726', 0.6, 15)
    corridorLight.position.set(15, 6, -12)
    scene.add(corridorLight)
    lightsRef.current.push(corridorLight)

    return () => {
      // 清理本组件创建的光源
      lightsRef.current.forEach(light => scene.remove(light))
      lightsRef.current = []
    }
  }, [scene])

  // 根据 enabled 开关灯光可见性
  useEffect(() => {
    // 开关所有真实 Light（不再改动发光材质/灯带）
    lightsRef.current.forEach((light: THREE.Light) => {
      light.visible = enabled
    })
  }, [enabled])

  return null
}

// 主组件
export function Index() {
  const [exitOpen, setExitOpen] = useState(false)
  const [showControls, setShowControls] = useState(true) // 控制操作说明弹框显示
  const [lightsOn, setLightsOn] = useState(true) // 全局灯光开关
  const [cameraMode, setCameraMode] = useState<CameraMode>('firstPerson') // 视角模式
  const [isPlayerMoving, setIsPlayerMoving] = useState(false) // 玩家移动状态
  const [playerMoveDirection, setPlayerMoveDirection] = useState<'forward' | 'backward' | 'left' | 'right' | 'idle'>('idle') // 移动方向
  const [isPlayerJumping, setIsPlayerJumping] = useState(false) // 玩家跳跃状态
  const [imageInteractionState, setImageInteractionState] = useState<{
    nearestImage: {
      name: string
      position: THREE.Vector3
      distance: number
      imageUrl: string
    } | null
    isViewingImage: boolean
    viewingImageData: {
      name: string
      position: THREE.Vector3
      imageUrl: string
      originalCameraPosition: THREE.Vector3
      originalCameraRotation: THREE.Euler
    } | null
  } | null>(null) // 图片交互状态
  
  // 图片朗读功能
  const { checkPhotoInteraction, isReading, currentPhoto } = usePhotoNarrator()
  
  const navigate = useNavigate()
  const [searchParams] = useSearchParams()
  
  // 监听图片交互状态
  useEffect(() => {
    const checkImageState = () => {
      if (window.imageInteractionState) {
        setImageInteractionState(window.imageInteractionState)
        
        // 检查是否需要朗读（即使nearestImage为null也要调用，以便停止播放）
        if (window.imageInteractionState.cameraPosition && window.imageInteractionState.cameraRotation) {
          checkPhotoInteraction(
            window.imageInteractionState.nearestImage, // 可能为null
            window.imageInteractionState.cameraPosition,
            window.imageInteractionState.cameraRotation
          )
        }
      }
    }
    
    const interval = setInterval(checkImageState, 100) // 每100ms检查一次
    return () => clearInterval(interval)
  }, [checkPhotoInteraction])
  
  // 角色选择逻辑
  const getSelectedCharacter = (): string => {
    // 1. 优先从URL参数读取
    const urlCharacter = searchParams.get('character')
    
    if (urlCharacter) {
      // 存储到LocalStorage作为备份
      localStorage.setItem('selectedCharacter', urlCharacter)
      return `/${urlCharacter}.glb`
    }
    
    // 2. 从LocalStorage读取
    const storedCharacter = localStorage.getItem('selectedCharacter')
    
    if (storedCharacter) {
      return `/${storedCharacter}.glb`
    }
    
    // 3. 默认角色
    return '/avatar.glb'
  }
  
  const selectedCharacterModel = getSelectedCharacter()
  
  // 玩家位置和旋转状态 - 修复Y坐标让角色站在地面上
  const playerPosition = useRef(new THREE.Vector3(-28, 0, 0))  // Y=0 站在地面上
  const playerRotation = useRef(new THREE.Euler(0, 3 * Math.PI / 2, 0, 'YXZ'))
  
  // 视角切换函数
  const toggleCameraMode = () => {
    setCameraMode(prev => {
      if (prev === 'firstPerson') {
        // 切换到第三人称时，让人物面向房间内部（90度方向）
        playerRotation.current.y = Math.PI / 2
        return 'thirdPerson'
      } else {
        return 'firstPerson'
      }
    })
  }

  // 处理退出按钮点击
  const handleExitClick = () => {
    
    // 立即解锁鼠标
    if (document.pointerLockElement) {
      try {
        document.exitPointerLock()
      } catch (error) {
        console.error('鼠标解锁失败:', error)
      }
    }
    
    // 使用requestAnimationFrame确保在下一帧执行，避免阻塞
    requestAnimationFrame(() => {
      // 再次检查并尝试解锁
      if (document.pointerLockElement) {
        try {
          document.exitPointerLock()
        } catch (error) {
          console.error('强制解锁失败:', error)
        }
      }
      
      // 显示对话框
      setExitOpen(true)
    })
  }

  // 处理确认退出
  const handleConfirmExit = () => {
    setExitOpen(false)
    navigate('/home') // 直接跳转，不需要再解锁鼠标
    
    // 延迟刷新页面，确保数字人能正常显示
    setTimeout(() => {
      window.location.reload()
    }, 500)
  }

  // 处理取消退出
  const handleCancelExit = () => {
    setExitOpen(false)
    // 确保鼠标保持解锁状态，让用户点击屏幕时重新锁定
    if (document.pointerLockElement) {
      try {
        document.exitPointerLock()
      } catch (error) {
        console.warn('Failed to exit pointer lock on cancel:', error)
      }
    }
  }

  // 处理操作说明弹框关闭
  const handleCloseControls = () => {
    setShowControls(false)
  }

  // 监听屏幕点击，用于重新锁定鼠标
  useEffect(() => {
    const handleCanvasClick = (event: MouseEvent) => {
      // 只有在弹窗关闭、操作说明关闭且鼠标未锁定时才重新锁定
      if (!exitOpen && !showControls && !document.pointerLockElement) {
        // 确保点击的是canvas区域，而不是其他UI元素
        const target = event.target as HTMLElement
        if (target && target.tagName === 'CANVAS') {
          const canvas = document.querySelector('canvas')
          if (canvas) {
            canvas.requestPointerLock().catch((error) => {
              console.warn('Failed to request pointer lock:', error)
            })
          }
        }
      }
    }

    // 添加点击事件监听器
    document.addEventListener('click', handleCanvasClick)
    
    return () => {
      document.removeEventListener('click', handleCanvasClick)
    }
  }, [exitOpen, showControls])

  // 添加全局键盘监听器，处理ESC键和V键
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        // ESC键按下时，确保鼠标解锁
        if (document.pointerLockElement) {
          try {
            document.exitPointerLock()
          } catch (error) {
            console.warn('ESC key unlock failed:', error)
          }
        }
      } else if (event.key.toLowerCase() === 'v') {
        // V键切换视角模式
        toggleCameraMode()
      }
    }

    document.addEventListener('keydown', handleKeyDown)
    
    return () => {
      document.removeEventListener('keydown', handleKeyDown)
    }
  }, [])

  return (
    <div style={{ width: '100vw', height: '100vh', background: '#000' }}>
      <style>{`
        @keyframes pulse {
          0% { opacity: 1; }
          50% { opacity: 0.5; }
          100% { opacity: 1; }
        }
      `}</style>
      <Canvas
        camera={{ 
          position: [-28, 2, 0], 
          fov: 75
        }}
        shadows
        style={{ background: 'linear-gradient(to bottom, #87CEEB, #E0F6FF)' }}
      >
        <ExhibitionHallScene />
        <Lighting enabled={lightsOn} />
        <MovementControls 
          cameraMode={cameraMode}
          playerPosition={playerPosition}
          playerRotation={playerRotation}
          setIsPlayerMoving={setIsPlayerMoving}
          setPlayerMoveDirection={setPlayerMoveDirection}
          setIsPlayerJumping={setIsPlayerJumping}
        />
        <MouseLookControls 
          cameraMode={cameraMode}
          playerPosition={playerPosition}
          playerRotation={playerRotation}
        />
        <ImageInteractionLogic />
        <Suspense fallback={null}>
          <PlayerCharacter 
            position={playerPosition}
            rotation={playerRotation}
            visible={cameraMode === 'thirdPerson'}
            isMoving={isPlayerMoving}
            moveDirection={playerMoveDirection}
            isJumping={isPlayerJumping}
            characterModel={selectedCharacterModel}
          />
        </Suspense>
      </Canvas>
      
      {/* 视角切换按钮 */}
      <button
        onClick={(e) => {
          e.preventDefault()
          e.stopPropagation()
          toggleCameraMode()
        }}
        onMouseDown={(e) => {
          e.preventDefault(); e.stopPropagation()
        }}
        style={{
        position: 'absolute',
        top: '20px',
          right: '280px',
        color: '#ffffff',
          background: cameraMode === 'firstPerson' ? 'rgba(0, 100, 200, 0.85)' : 'rgba(200, 100, 0, 0.85)',
          padding: '10px 16px',
          borderRadius: '8px',
          border: 'none',
          cursor: 'pointer',
        fontFamily: 'Arial, sans-serif',
        fontSize: '14px',
        zIndex: 1000
        }}
      >{cameraMode === 'firstPerson' ? '第三人称' : '第一人称'}</button>

      {/* 灯光开关 */}
      <button
        onClick={(e) => {
          e.preventDefault()
          e.stopPropagation()
          setLightsOn(v => !v)
        }}
        onMouseDown={(e) => {
          e.preventDefault(); e.stopPropagation()
        }}
        style={{
        position: 'absolute',
        top: '20px',
          right: '140px',
        color: '#ffffff',
          background: lightsOn ? 'rgba(0, 128, 0, 0.85)' : 'rgba(128, 128, 128, 0.85)',
          padding: '10px 16px',
          borderRadius: '8px',
          border: 'none',
          cursor: 'pointer',
        fontFamily: 'Arial, sans-serif',
        fontSize: '14px',
        zIndex: 1000
        }}
      >{lightsOn ? '关闭灯光' : '开启灯光'}</button>

      {/* 退出按钮 */}
      <button
        onClick={(e) => {
          e.preventDefault()
          e.stopPropagation()
          handleExitClick()
        }}
        onMouseDown={(e) => {
          e.preventDefault()
          e.stopPropagation()
        }}
        style={{
        position: 'absolute',
        top: '20px',
        right: '20px',
        color: '#ffffff',
          background: 'rgba(255, 0, 0, 0.8)',
          padding: '10px 16px',
          borderRadius: '8px',
          border: 'none',
          cursor: 'pointer',
        fontFamily: 'Arial, sans-serif',
          fontSize: '14px',
        zIndex: 1000
        }}
      >退出展览馆</button>

      {/* 操作说明弹框 */}
      {showControls && (
        <div style={{
          position: 'fixed',
          top: 0,
          left: 0,
          width: '100vw',
          height: '100vh',
          background: 'rgba(0, 0, 0, 0.75)',
          backdropFilter: 'blur(4px)',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          zIndex: 2000,
          animation: 'fadeIn 0.3s ease-out'
        }}>
          <div style={{
            background: 'linear-gradient(135deg, #ffffff 0%, #f8fafc 100%)',
            borderRadius: '20px',
            padding: '40px',
            maxWidth: '600px',
            width: '90%',
            boxShadow: '0 25px 50px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(255, 255, 255, 0.1)',
            textAlign: 'center',
            position: 'relative',
            overflow: 'hidden'
          }}>
            {/* 装饰性背景元素 */}
            <div style={{
              position: 'absolute',
              top: '-50px',
              right: '-50px',
              width: '100px',
              height: '100px',
              background: 'linear-gradient(45deg, #667eea, #764ba2)',
              borderRadius: '50%',
              opacity: 0.1
            }} />
            <div style={{
              position: 'absolute',
              bottom: '-30px',
              left: '-30px',
              width: '60px',
              height: '60px',
              background: 'linear-gradient(45deg, #f093fb, #f5576c)',
              borderRadius: '50%',
              opacity: 0.1
            }} />
            
            <div style={{ position: 'relative', zIndex: 1 }}>
              <h2 style={{
                margin: '0 0 8px 0',
                color: '#1a202c',
                fontSize: '28px',
                fontWeight: '700',
                letterSpacing: '-0.5px'
              }}>操作说明</h2>
              
              <p style={{
                margin: '0 0 35px 0',
                color: '#718096',
                fontSize: '16px',
                fontWeight: '400'
              }}>欢迎来到3D展览馆，请先了解基本操作</p>
              
              {/* 左右分栏布局 */}
              <div style={{
                display: 'flex',
                gap: '30px',
                marginBottom: '35px',
                alignItems: 'flex-start'
              }}>
                {/* 左侧：WASD 键盘布局 */}
                <div style={{
                  flex: 1,
                  display: 'flex',
                  flexDirection: 'column',
                  alignItems: 'center',
                  gap: '12px'
                }}>
                {/* W 键 */}
                <div style={{
                  // display: 'flex',
                  alignItems: 'center',
                  gap: '16px',
                  padding: '16px 24px',
                  background: 'rgba(255, 255, 255, 0.8)',
                  borderRadius: '12px',
                  border: '1px solid rgba(226, 232, 240, 0.8)',
                  transition: 'all 0.2s ease',
                  cursor: 'default'
                }}>
                  <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    width: '48px',
                    height: '48px',
                    background: 'linear-gradient(135deg, #3378DD 0%, #2563eb 100%)',
                    color: '#ffffff',
                    borderRadius: '12px',
                    fontWeight: '600',
                    fontSize: '18px',
                    boxShadow: '0 4px 12px rgba(102, 126, 234, 0.3)',
                    position: 'relative'
                  }}>
                    <span style={{ fontSize: '14px', marginRight: '2px' }}>↑</span>
                    <span style={{ fontSize: '12px', fontWeight: '700' }}>W</span>
      </div>
                  <span style={{
                    color: '#2d3748',
                    fontSize: '16px',
                    fontWeight: '500',
                    flex: 1
                  }}>前进</span>
                </div>

                {/* A S D 键行 */}
                <div style={{
                  display: 'flex',
                  gap: '12px',
                  alignItems: 'center'
                }}>
                  {/* A 键 */}
                  <div style={{
                    // display: 'flex',
                    alignItems: 'center',
                    gap: '16px',
                    padding: '16px 24px',
                    background: 'rgba(255, 255, 255, 0.8)',
                    borderRadius: '12px',
                    border: '1px solid rgba(226, 232, 240, 0.8)',
                    transition: 'all 0.2s ease',
                    cursor: 'default'
                  }}>
                    <div style={{
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      width: '48px',
                      height: '48px',
                      background: 'linear-gradient(135deg, #3378DD 0%, #2563eb 100%)',
                      color: '#ffffff',
                      borderRadius: '12px',
                      fontWeight: '600',
                      fontSize: '18px',
                      boxShadow: '0 4px 12px rgba(102, 126, 234, 0.3)',
                      position: 'relative'
                    }}>
                      <span style={{ fontSize: '14px', marginRight: '2px' }}>←</span>
                      <span style={{ fontSize: '12px', fontWeight: '700' }}>A</span>
                    </div>
                    <span style={{
                      color: '#2d3748',
                      fontSize: '16px',
                      fontWeight: '500',
                      flex: 1
                    }}>向左</span>
                  </div>

                  {/* S 键 */}
                  <div style={{
                    // display: 'flex',
                    alignItems: 'center',
                    gap: '16px',
                    padding: '16px 24px',
                    background: 'rgba(255, 255, 255, 0.8)',
                    borderRadius: '12px',
                    border: '1px solid rgba(226, 232, 240, 0.8)',
                    transition: 'all 0.2s ease',
                    cursor: 'default'
                  }}>
                    <div style={{
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      width: '48px',
                      height: '48px',
                      background: 'linear-gradient(135deg, #3378DD 0%, #2563eb 100%)',
                      color: '#ffffff',
                      borderRadius: '12px',
                      fontWeight: '600',
                      fontSize: '18px',
                      boxShadow: '0 4px 12px rgba(102, 126, 234, 0.3)',
                      position: 'relative'
                    }}>
                      <span style={{ fontSize: '14px', marginRight: '2px' }}>↓</span>
                      <span style={{ fontSize: '12px', fontWeight: '700' }}>S</span>
                    </div>
                    <span style={{
                      color: '#2d3748',
                      fontSize: '16px',
                      fontWeight: '500',
                      flex: 1
                    }}>后退</span>
                  </div>

                  {/* D 键 */}
                  <div style={{
                    // display: 'flex',
                    alignItems: 'center',
                    gap: '16px',
                    padding: '16px 24px',
                    background: 'rgba(255, 255, 255, 0.8)',
                    borderRadius: '12px',
                    border: '1px solid rgba(226, 232, 240, 0.8)',
                    transition: 'all 0.2s ease',
                    cursor: 'default'
                  }}>
                    <div style={{
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      width: '48px',
                      height: '48px',
                      background: 'linear-gradient(135deg, #3378DD 0%, #2563eb 100%)',
                      color: '#ffffff',
                      borderRadius: '12px',
                      fontWeight: '600',
                      fontSize: '18px',
                      boxShadow: '0 4px 12px rgba(102, 126, 234, 0.3)',
                      position: 'relative'
                    }}>
                      <span style={{ fontSize: '14px', marginRight: '2px' }}>→</span>
                      <span style={{ fontSize: '12px', fontWeight: '700' }}>D</span>
                    </div>
                    <span style={{
                      color: '#2d3748',
                      fontSize: '16px',
                      fontWeight: '500',
                      flex: 1
                    }}>向右</span>
                  </div>
                </div>
                </div>

                {/* 右侧：其他控制键 */}
                <div style={{
                  flex: 1,
                  display: 'flex',
                  flexDirection: 'column',
                  gap: '20px'
                }}>
                  {[
                    { key: '空格', action: '跳跃', icon: '⤴' },
                    { key: 'V', action: '切换视角', icon: '👁' },
                    { key: '鼠标', action: '控制视角', icon: '🖱' }
                  ].map((item, index) => (
                    <div key={index} style={{
                      display: 'flex',
                      alignItems: 'center',
                      gap: '16px',
                      padding: '16px',
                      background: 'rgba(255, 255, 255, 0.8)',
                      borderRadius: '12px',
                      border: '1px solid rgba(226, 232, 240, 0.8)',
                      transition: 'all 0.2s ease',
                      cursor: 'default'
                    }}>
                      <div style={{
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        width: '48px',
                        height: '48px',
                        background: 'linear-gradient(135deg, #3378DD 0%, #2563eb 100%)',
                        color: '#ffffff',
                        borderRadius: '12px',
                        fontWeight: '600',
                        fontSize: '18px',
                        boxShadow: '0 4px 12px rgba(51, 120, 221, 0.3)',
                        position: 'relative'
                      }}>
                        <span style={{ fontSize: '14px', marginRight: '2px' }}>{item.icon}</span>
                        <span style={{ fontSize: '12px', fontWeight: '700' }}>{item.key}</span>
                      </div>
                      <span style={{
                        color: '#2d3748',
                        fontSize: '16px',
                        fontWeight: '500',
                        flex: 1
                      }}>{item.action}</span>
                    </div>
                  ))}
                </div>
              </div>
              
              <div style={{
                background: '#787878',
                padding: '10px',
                borderRadius: '16px',
                marginBottom: '30px',
                color: '#ffffff',
                position: 'relative',
                overflow: 'hidden'
              }}>
                <div style={{
                  position: 'absolute',
                  top: '-10px',
                  right: '-10px',
                  fontSize: '24px',
                  opacity: 0.3
                }}>💡</div>
                <p style={{
                  margin: 0,
                  fontSize: '15px',
                  fontWeight: '500',
                  lineHeight: '1.5',
                  position: 'relative',
                  zIndex: 1
                }}>
                  点击屏幕任意位置开始体验，按 <strong>V</strong> 键切换视角，按 <strong>ESC</strong> 键可解锁鼠标
                </p>
              </div>
              
              <button
                onClick={handleCloseControls}
                style={{
                  background: 'linear-gradient(135deg, #3378DD 0%, #2563eb 100%)',
                  color: '#ffffff',
                  border: 'none',
                  padding: '16px 40px',
                  borderRadius: '12px',
                  fontSize: '18px',
                  fontWeight: '600',
                  cursor: 'pointer',
                  transition: 'all 0.3s ease',
                  boxShadow: '0 8px 25px rgba(51, 120, 221, 0.3)',
                  position: 'relative',
                  overflow: 'hidden'
                }}
                onMouseOver={(e) => {
                  e.currentTarget.style.transform = 'translateY(-2px)'
                  e.currentTarget.style.boxShadow = '0 12px 35px rgba(51, 120, 221, 0.4)'
                }}
                onMouseOut={(e) => {
                  e.currentTarget.style.transform = 'translateY(0)'
                  e.currentTarget.style.boxShadow = '0 8px 25px rgba(51, 120, 221, 0.3)'
                }}
              >
                开始体验
              </button>
            </div>
          </div>
        </div>
      )}

      <ConfirmDialog
        isOpen={exitOpen}
        title="确认退出"
        message="确定要退出展览馆吗？"
        confirmText="退出"
        cancelText="取消"
        onConfirm={handleConfirmExit}
        onCancel={handleCancelExit}
      />

      {/* 图片交互UI */}
      {imageInteractionState?.nearestImage && !imageInteractionState?.isViewingImage && (
        <div style={{
          position: 'fixed',
          top: '50%',
          left: '50%',
          transform: 'translate(-50%, -50%)',
          background: 'rgba(0, 0, 0, 0.8)',
          color: 'white',
          padding: '20px 30px',
          borderRadius: '10px',
          fontSize: '18px',
          fontWeight: 'bold',
          zIndex: 1000,
          textAlign: 'center',
          border: '2px solid #00ff00',
          boxShadow: '0 0 20px rgba(0, 255, 0, 0.5)'
        }}>
          <div>长按 F 键查看 {imageInteractionState.nearestImage.name}</div>
          <div style={{ fontSize: '14px', marginTop: '5px', opacity: 0.8 }}>
            距离: {imageInteractionState.nearestImage.distance.toFixed(1)}m
          </div>
        </div>
      )}

      {/* 朗读状态显示 */}
      {isReading && (
        <div style={{
          position: 'fixed',
          top: '80px',
          left: '50%',
          transform: 'translateX(-50%)',
          background: 'rgba(0, 0, 0, 0.8)',
          color: 'white',
          padding: '10px 20px',
          borderRadius: '25px',
          fontFamily: 'Arial, sans-serif',
          fontSize: '16px',
          zIndex: 1500,
          display: 'flex',
          alignItems: 'center',
          gap: '10px'
        }}>
          <div style={{
            width: '12px',
            height: '12px',
            borderRadius: '50%',
            background: '#ff6b6b',
            animation: 'pulse 1s infinite'
          }} />
          <span>正在朗读: {currentPhoto}</span>
        </div>
      )}

      {/* 查看模式UI - 弹出图片框 */}
      {imageInteractionState?.isViewingImage && imageInteractionState?.viewingImageData && (
        <div style={{
          position: 'fixed',
          top: 0,
          left: 0,
          width: '100vw',
          height: '100vh',
          background: 'rgba(0, 0, 0, 0.9)',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          zIndex: 2000,
          backdropFilter: 'blur(5px)'
        }}>
          {/* 图片容器 */}
          <div style={{
            position: 'relative',
            maxWidth: '90vw',
            maxHeight: '90vh',
            background: 'white',
            borderRadius: '15px',
            padding: '20px',
            boxShadow: '0 25px 50px rgba(0, 0, 0, 0.5)',
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center'
          }}>
            {/* 标题 */}
            <div style={{
              fontSize: '24px',
              fontWeight: 'bold',
              color: '#333',
              marginBottom: '20px',
              textAlign: 'center'
            }}>
              {imageInteractionState.viewingImageData.name}
            </div>
            
            {/* 图片 */}
            <img 
              src={imageInteractionState.viewingImageData.imageUrl}
              alt={imageInteractionState.viewingImageData.name}
              style={{
                maxWidth: '100%',
                maxHeight: '70vh',
                objectFit: 'contain',
                borderRadius: '10px',
                boxShadow: '0 10px 30px rgba(0, 0, 0, 0.3)'
              }}
            />
            
            {/* 提示文字 */}
            <div style={{
              fontSize: '16px',
              color: '#666',
              marginTop: '20px',
              textAlign: 'center',
              fontStyle: 'italic'
            }}>
              长按 F 键查看，松手退出
            </div>
          </div>
        </div>
      )}
    </div>
  )
}

export default Index

